Getting screenshot via printwindow not redrawing if laptop screen off - python

My goal is to take screenshots off an application while the laptop screen is off, but instead the screenshot will always be the same as just before turning off the screen. It does not redraw itself once the screen is off, and remains frozen.
I'm obtaining a screenshot using printwindow from Python (using method described here: Python Screenshot of inactive window PrintWindow + win32gui
This method works nicely as long as I have my laptop screen on, but if I turn it off, it simply returns the last image before the screen turned off. I've tried using win32gui.RedrawWindow, hoping that this would force a redraw, but I haven't gotten it to work, even trying all the different flags. I've also tried getting screenshots via pyautogui, but this also has the same problem. Is there any way to redraw the application while the laptop screen is off?

It would be nice if there were a straightforward way to do what you want to do, but unfortunately it's just not possible without some convoluted low-level work.
In the underlying WinAPI, native windows redraw themselves only when they receive WM_PAINT messages, and they only receive WM_PAINT messages if they are visible. They don't get the messages if they're behind another window, or if they're dragged off screen, or minimized, or their visibility is set to False. They also aren't visible when the screen is off. Since they aren't visible, they simply never get told to redraw themselves. That's why the screen capture image doesn't change after the screen is turned off.
There is no command you can issue that will override this -- it is implemented as a fundamental part of the windowing paradigm.
One solution is to have the application paint itself in something that's not a window (e.g., a dialog box) and capture that rather than capturing the screen. You could also modify the application by overriding OnPaint and using a timer to invalidate and call your OnPaint function periodically (since WM_PAINT messages won't be received).
If it were me I'd override OnPaint, make my application draw itself to a background context bitmap rather than the normal window, then use a timer to invalidate and redraw periodically and just take the bitmap of the background context whenever I wanted to capture the output.
If you don't own the code for the applications that are running, you may still be able to get applications to redraw themselves by running everything in a virtual machine. I've done that successfully for headless computing in the past, but it was many OS versions ago and things may be different now, so YMMV...
Information on manual screenshots under VMWare is here.
Information on programmatic screenshots under Hyper-V is here.

Related

PyQT force rendering some widget before calling other function

I am designing a GUI for a Python project that manages some simulations. As the simulations take some time, I want to have a window that tells the user to wait, popping up when the simulation is started.
Currently, the code is like
def start_simulation(self):
self.calculation_running_dialog.show()
heavy_function_call(self)
self.calculation_running_dialog.hide()
However, I face the following problem: When the simulation is started the window does appear, but it is rendered with a transparent body in Ubuntu and with an empty (white) body in Windows. Only after the heavy function call has terminated, the window is rendered properly. How can I force the window to be displayed properly before the simulation starts?
Recently, I have asked a similar question here: PyQT force update textEdit before calling other function.
For that purpose, the repaint() function turned out to be the solution. But for the current problem, neither self.calculation_running_dialog.repaint() nor self.calculation_running_dialog.update() or self.calculation_running_dialog.textLabel.repaint() does the trick.
Any suggestions?

Seeking a simple way to display an image on an RPi and continue python execution

I'm transferring an application to an RPi, and I need a way to display full screen images using python (3) while code continues to execute. I would like to avoid delving into complicated GUI modules like Tkinter and Pygame. I just want images to fill the screen and stay there until the code replaces them or tells them to go away. If Tkinter or Pygame can do this, that would be fine, but it looks to me like they both enter loops that eventually require keyboard input. My application involves montiring sensors and external inputs, but there will be no keyboard attached. I've tried the following:
feh activated with subprocess.call (This displays the image, but the code stops executing until the image is cleared by a keystroke.
wand.display (this works but only shows a smallish window, not full screen)
fbi (couldn't get it to display an image)
xcd-open (works but opens in "Image Viewer" app in small window - no option for full screen without a mouse click)
I have not tried OpenCV. Seems like that might work, but that's a lot of infrastructure to bring in for this simple application.
For the record I've been to google and have put many hours into this. This request is a last resort.
If you want some pseudocode:
displayImage("/image_folder/image1.jpg" fullscreen = True)
time.sleep(1)
clearImage()
displayImage("/image_folder/image2.jpg" fullscreen = True)
You don't show how you tried with feh and a subprocess, but maybe try starting it in the background so it doesn't block your main thread:
subprocess.call("feh -F yourImage.jpg &", shell=True)
Note that background processes, i.e. those started with &, are using a feature of the shell, so I have set shell=True.
Then, before you display the next image, kill the previous instance:
subprocess.call("pkill feh")
Alternatively, if you know the names of all the images you plan to display in advance, you could start feh in "Slideshow mode" (by passing in all the image names on startup), and then deliver signal SIGUSR1 each time you want to advance the image:
os.kill(os.getpid(...), signal.SIGUSR1)
If the above doesn't work, please click edit under your original question and add in the output from the following commands so we can go down the framebuffer route:
fbset -fb /dev/fb0
tvservice -d edid
edidparser edid

Python, transparent window with a red outine of a rectangle

Hi I am new to this whole coding thing I was suggested to use Python. The version I have now is 2.7. I need help with making a transparent window to the copacity of 100 so that you can actually see through it and I also want to know how to make a fairy thick, out line of a rectangle in the colour red.
Help me please :S Thanks!
Unfortunatelly, there is not such an easy thing as sa "trasnparent window" - althougmodern widnow managaers do have various opacity controls for the windows, those just affect the windows as a whole - and do not integrate at all with the program running "inside" the windows. There may even be, for some of them, a way to call functions to explicitly set up the opacity level of a given window, but I don't think it willbe possible for all of them.
That said, it is possible to get grab of the "root" window and draw directly on the screen - -bypassing the window manager. There are APIs for that at least on Windows and Linux (you have to mention in what operating system you need that working) - but it will amount to not a trivial research work, since this is not what is expected of a "well behaved app" - for which the GUI toolkits are written and documented. You will need to write xlib code in Linux, and directly call win32 api's on windows - both are possible from Python - as possible as under-documented.
And once you get to draw the rectangle, since you are bypassing the window manager, you willhave to care about every low-level detail of your app: mouse event handling, screen-redrawing (and notifying the system of drawing taking effect over other windows), and so on.

Which display manager for a non interactive Python app and mplayer?

I am developing an application that will run on Linux to run fullscreen all the time (no menus or trays or anything will be visible).
The application is going to be developed in Python, not that that matters as far as the window manager, but what I am having a hard time with is choosing a window manager.
I need something with the smallest possible footprint, that will let me run a graphical Python app and have an mplayer window at the same time, at widescreen resolutions (widescreen, 16:10,16:9, etc). Other than that, it doesn't need a lot of features, but the end footprint size is the most important thing I'll be looking at.
What window manager would you recommend?
EDIT: There won't be any interaction with the application needed.
You don't actually need any window manager or display manager. All you need to do is open your initial window with the same geometry as the root window. I suppose you could even draw directly into the root window if you wanted.
If you are using some display library it probably has an easy way to open a full screen window. For example using a recent enough version of SDL through pygame you can do
pygame.display.init()
surface = pygame.display.set_mode((0,0),pygame.FULLSCREEN,0)
to get a window that fills the entire screen. This will work even if there is no window manager running.
As for mplayer, it accepts the -geometry flag, so you can use something like mplayer -geometry 640x480+20+20 to display the mplayer window 20 pixels from the top 20 pixels from the left and with a size of 640x480 pixels.
You probably meant window manager. Display manages are KDM, GDM and the like. Windoe managers, to name, GNOME, Xfce, KDE, ratpoison, fvwm, twm, blackbox are a few. ratpoison gives full screen to the application that is in the foreground but demands heavy keyboard interaction (hence the name ratpoison) and no mouse interaction at all.
I assume you'll be running both your python GUI and mplayer in some sort of geometries combination that shows both at the same time, filling the screen.
As commented, you should not need a window manager to achieve that. You could have your python GUI app get command-line parameters for setting its window geometry and also call fullscreen mplayer with the -geometry parameter. That should fill the screen as expected, without any window decorations.
Now you could have the startx script called for the user running it all and have a custom ~/.xinitrc script doing something like:
#!/bin/sh
exec python my_gui_app --whatever-sets-geom &
exec mplayer -fs video.avi
If yout pyhon app will instead be launching mplayer then just leave the first 'exex' call (remove the '&') and have it call mplayer as desired with the expected dimensions in '-fs' mode.
Please note you may need to use something like the 'xset' program to disable monitor blanking due to energy savings, hide the cursor (although IIRC that's something mplayer does for its own window), and things like that.
Also, somethimes running, for example, GTK apps on a bare X display may end up using an "ugly" theme, so you may need to have the toolkit style configuration taken care of someway.
I am doing something similar on my "set-top box" and I don't use any window manager.
It boots debian, and from inittab I auto-login the user that runs the display. That user's .profile starts X, which runs .xinitrc, which starts my python app that runs as a network server in front of mplayer (running mplayer in -slave mode).
My python app does not have a GUI element - only mplayer runs on the X display. But in your case, it should be no different. As I mentioned in a comment to another answer, you may want to look into how you can reparent mplayer's window to give you greater control over its placement and/or movement/size.
Doing it this way avoided a display manager and a window manager. This simplifies the solution, boots faster and uses a smaller footprint (it runs of an SD card, with heaps of room to spare).
I realize this is an old question, but I use openbox on my system, I have created a custom config file that disables all mouse keyboard shortcuts, and removes borders etc on the applications.
In the openbox config i even created some secret shortcuts that can run fx. an xterm for debugging live on the box.
The openbox documentation was very helpful in figuring everything out, I did the config in about 30 minutes.

GUI app spawned from a LocalSystem Service (via CreateProcessAsUser) does not have focus

I have created a service which display a sort of splash screen on the desktop of a specific user and only when that user is logged in (kiosk user).
That splash screen, once entered a valid code, will tell that to the service and the service goes to sleep for an x amount of time (depending of the code).
The splash screen simply quits. Now when the service wakes up it sees that the splash is no longer there and so start it up.
This all is working, the only problem is that the launched application does not have focus, i.e. if I am working in notepad and the time is up, the splash screen is displayed (full screen though) behind notepad.
I only have to worry about Windows Vista, I am coding in Python using win32 extensions but I believe this problem lies in CreateProcessAsUser when called from the LocalSystem account.
Update:
The 'problem' is actually an on purpose limitation to prevent 'irritating' applications like mine from stealing focus.
You can change the behaviour by setting:
win32gui.SystemParametersInfo(win32con.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0)
which is equivalent in temporarily setting the registry value:
HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout
This must be done as the user itself, so either build it in the app you are launching or build an launching helper for the app you want to launch.
However an application might want to prevent getting it's focus stolen by using some API call which I don't remember right now.
A probably good solution would be to find all window handles currently from that user and then use each of these handles to use win32gui.ShowWindow(handle, command) to minimize it.
Although for this particular problem setting the locktimeout setting was enough.
If anyone wonders how I managed to launch an application to a desktop from a service, here is a link to the code.
Have you tried launching another processes than your own from the service to see if it gets focus? Like notepad and see if it steals focus from your browser? If so perhaps its the program that can take back the focus when it starts.
I otherwise beilive it's the wShowWindow attribute from the STARTUPINFO struct the lpStartupInfo points to that should control it. You also need STARTF_USESHOWWINDOW in dwFlags to use nShowWindow. The values should be SW_SHOW i think, they are listed for the ShowWindow function if you want to try other.
For various very legitimated reasons, Microsoft would rather not see a service launching an app and stealing focus, however I found the following work around to still accomplish what I want.
The original intend is to have a kiosk like application hindered by a pass code like splash screen, which upon entering a 8 character code closes the splash screen for a period time as in the pass code defined. Originally the actual application to use was started by the autostart folder.
However I now rewrote it that it is launched from my service, this way I can hide the application by launching an helper application from the service that just hides the program and launches the splash screen, upon exiting the splash screen the program is returned to the previous state.

Categories

Resources