Get windows, move and resize on Windows - python

I'm on Windows and I need to get one window by title name then move and resize it. The code below is for unix only because fcntl doesn't exist on Windows.
import Xlib
import Xlib.display
display = Xlib.display.Display()
screen = display.screen()
root = screen.root
tree = root.query_tree()
wins = tree.children
for win in wins:
print (win.get_wm_name())
win.configure(x=123, y=345, width=678, height=910)
win.change_attributes(win_gravity=X.NorthWestGravity, bit_gravity=X.StaticGravity)
ModuleNotFoundError: No module named 'fcntl'
Do you have an alternative to this please ? Then how to get the windows which has the title "Hello there" ?

I have found this and it is working :
import win32gui, win32con
win2find = 'Skype'
whnd = win32gui.FindWindowEx(None, None, None, win2find)
if not (whnd == 0):
print('Skype')
win32gui.SetWindowPos(whnd, win32con.HWND_NOTOPMOST, 0, 0, 500, 600, 0)

Related

Make tkinter window always on back

I am trying to make a desktop overlay for windows.
Here is my code:
from tkinter import *
from win32gui import SetWindowPos
from win32con import *
from win32api import Sleep
from threading import Thread
class Desktop:
def Desktop(self):
self.desktoptk = Tk()
tk = self.desktoptk
tk.overrideredirect(True)
tk.geometry(f'{tk.winfo_screenwidth()}x{tk.winfo_screenheight()}+0+0')
def sendtoback():
hwnd = tk.winfo_id()
print(hwnd)
def send():
while True:
Sleep(10)
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE)
Thread(target=send).start()
tk.after(200, sendtoback)
bg = PhotoImage(file=R'data\bg.png')
Bg = Label(image=bg)
Bg.image = bg
Bg.place(x=0, y=0)
tk.mainloop()
Desktop().Desktop()
I didn't found anything in the internet what helps me, and i haven't come up with a solution.
I need to make my window to be always on back (opposite of always on top).

DearPyGui: Main window always on top

With dearpygui, I would like to have the main window (the one that contains all the other windows) to always be on top, even if it does not have focus.
Here is what I have so far :
from dearpygui.core import *
from dearpygui.simple import *
with window('MainWindow', width=500, height=500):
add_button('Read screen')
I went with this solution for now. I'll edit my answer if it gets supported by the library. This is a feature in their roadmap for now (see this issue).
from multiprocessing import Process
from time import sleep
import win32con
import win32gui
from dearpygui.core import *
from dearpygui.simple import *
with window('MainWindow', width=500, height=500):
add_button('Read screen')
if __name__ == '__main__':
# you have to make a new process for this in order to be able
# to call win32gui.FindWindow on your displayed window
p = Process(target=start_dearpygui)
p.start()
# sleep for a while to let your window get displayed
sleep(4)
hwnd = win32gui.FindWindow('DearPyGui', None)
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 100, 100, 300, 200, 0)

Python: How can I get the video resolution from a Gst video playbin?

I have the following code that works and displays a video in a window. Can someone help me and give a simple python example on how I can extract the video resolution ( width x height ) of the video file ?
I am stuck on this since several days ... and any help would be appreciated.
import os
import Tkinter as tkinter
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst, GObject, GstVideo
def set_frame_handle(bus, message, frame_id):
if not message.get_structure() is None:
if message.get_structure().get_name() == 'prepare-window-handle':
display_frame = message.src
display_frame.set_property('force-aspect-ratio', True)
display_frame.set_window_handle(frame_id)
window = tkinter.Tk()
window.title('')
window.geometry('400x300-30-100')
Gst.init(None)
GObject.threads_init()
display_frame = tkinter.Frame(window, bg='')
display_frame.place(relx = 0, rely = 0, anchor = tkinter.NW, relwidth = 1, relheight = 1)
frame_id = display_frame.winfo_id()
player = Gst.ElementFactory.make('playbin', None)
filepath = os.path.realpath('kbps.mp4')
filepath2 = "file:///" + filepath.replace('\\', '/').replace(':', '|')
print filepath2
player.set_property('uri', filepath2)
player.set_state(Gst.State.PLAYING)
bus = player.get_bus()
bus.enable_sync_message_emission()
bus.connect('sync-message::element', set_frame_handle, frame_id)
window.geometry('400x300+30+300')
window.update
window.mainloop()
Once the URI is set, set your pipeline into PAUSED state. Once that has been done, you should be prerolled, and can check the current caps on the gst-video-pad. For example:
self._playBin.set_state(Gst.State.PAUSED)
self._playBin.get_state(5000000000)
videoPad=self._playBin.emit("get-video-pad", 0)
videoPadCapabilities=videoPad.get_current_caps()(success, videoWidth) = \
videoPadCapabilities.get_structure(0).get_int("width")
(success, videoHeight) = \
videoPadCapabilities.get_structure(0).get_int("height")

Pygame set window on top without changing it's position

As I found in the following topic : How to make python window run as "Always On Top"?
I know how to put a window on top. But I would like to keep it at the same position. The autor says that he found a work around to find the x and y values. I would like to know how I can achieve that !
How can I get the x, y values of a pygame window ? Maybe it's a wrong way of doing.
The effect I am looking for is that the window goes on top when I trigger it with some function call.
For those who know League of legends, when a game starts, the window goes on top and remains at the same coordinates.
There's a shorter solution using the same function:
from ctypes import windll
SetWindowPos = windll.user32.SetWindowPos
NOSIZE = 1
NOMOVE = 2
TOPMOST = -1
NOT_TOPMOST = -2
def alwaysOnTop(yesOrNo):
zorder = (NOT_TOPMOST, TOPMOST)[yesOrNo] # choose a flag according to bool
hwnd = pygame.display.get_wm_info()['window'] # handle to the window
SetWindowPos(hwnd, zorder, 0, 0, 0, 0, NOMOVE|NOSIZE)
I found a solution that seems pretty well done:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ctypes import windll, Structure, c_long, byref #windows only
class RECT(Structure):
_fields_ = [
('left', c_long),
('top', c_long),
('right', c_long),
('bottom', c_long),
]
def width(self): return self.right - self.left
def height(self): return self.bottom - self.top
def onTop(window):
SetWindowPos = windll.user32.SetWindowPos
GetWindowRect = windll.user32.GetWindowRect
rc = RECT()
GetWindowRect(window, byref(rc))
SetWindowPos(window, -1, rc.left, rc.top, 0, 0, 0x0001)
Now in order to put a window on top, simply call onTop(pygame.display.get_wm_info()['window']) to handle your pygame window.
This worked for me
import win32gui
import win32con
win32gui.SetWindowPos(pygame.display.get_wm_info()['window'], win32con.HWND_TOPMOST, 0,0,0,0, win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
The window doesn't move because I used the SWP_NOMOVE tag
Getting current window position:
from ctypes import POINTER, WINFUNCTYPE, windll
from ctypes.wintypes import BOOL, HWND, RECT
# get our window ID:
hwnd = pygame.display.get_wm_info()["window"]
# Jump through all the ctypes hoops:
prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
paramflags = (1, "hwnd"), (2, "lprect")
GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
# finally get our data!
rect = GetWindowRect(hwnd)
print "top, left, bottom, right: ", rect.top, rect.left, rect.bottom, rect.right
# bottom, top, left, right: 644 98 124 644
Putting the window on the foreground:
x = rect.left
y = rect.top
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
I am using a Windows 11 system with Python 3.11.2 and for some reason, the SetWindowPos from windll.user32 library does not work. However the same SetWindowPos function from win32gui library works perfectly. Just do the exact answer #ZiyadCodes gave earlier.
To install required libraries:
$ pip install win32gui
$ pip install win32con
To keep pygame window always on top:
import win32gui
from win32con import SetWindowPos
SetWindowPos(pygame.display.get_wm_info()['window'], win32con.HWND_TOPMOST, 0,0,0,0, win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)

Python screenshot 2+ monitors (windows)

How to make a screenshot with python, if connected to multiple monitors?
I tried:
import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')
import ImageGrab
im = ImageGrab.grab()
im.save('test.png', 'PNG')
Both options provide a screenshot, only the primary monitor
If I use winapi:
hWnd = win32gui.FindWindow(None, win_name)
dc = win32gui.GetWindowDC(hWnd)
i_colour = int(win32gui.GetPixel(dc,int(x),int(y)))
rgb = ((i_colour & 0xff), ((i_colour >> 8) & 0xff), ((i_colour >> 16) & 0xff))
I get a picture from a window in the second monitor. But it will be very slow.
If I press key 'printscreen' in the clipboard will be a normal screenshot, with all monitors. Is there a option to get a Full screenshot in Python?
My Desktopmagic library provides this functionality for Python 2.6, 2.7, and 3.3+. It can return a PIL/Pillow Image or write a BMP.
Using a mix of wxPython, win32api and ctypes:
import wx, win32api, win32gui, win32con, ctypes
class App(wx.App):
def OnInit(self):
dll = ctypes.WinDLL('gdi32.dll')
for idx, (hMon, hDC, (left, top, right, bottom)) in enumerate(win32api.EnumDisplayMonitors(None, None)):
hDeskDC = win32gui.CreateDC(win32api.GetMonitorInfo(hMon)['Device'], None, None)
bitmap = wx.EmptyBitmap(right - left, bottom - top)
hMemDC = wx.MemoryDC()
hMemDC.SelectObject(bitmap)
try:
dll.BitBlt(hMemDC.GetHDC(), 0, 0, right - left, bottom - top, int(hDeskDC), 0, 0, win32con.SRCCOPY)
finally:
hMemDC.SelectObject(wx.NullBitmap)
bitmap.SaveFile('screenshot_%02d.bmp' % idx, wx.BITMAP_TYPE_BMP)
win32gui.ReleaseDC(win32gui.GetDesktopWindow(), hDeskDC)
return False
App(0)
install desktopmagic:
pip install Desktopmagic)
from __future__ import print_function
import desktopmagic
from desktopmagic.screengrab_win32 \
import(getDisplayRects,saveScreenToBmp,getScreenAsImage,getRectAsImage,getDisplaysAsImages)
""" getDisplayRects functions returns a list with all displays, in display order, like [(0, 0, 1280, 1024), (-1280, 0, 0, 1024), (1280, -176, 3200, 1024)] : (left, top, right, bottom)"""
screens=(getDisplayRects())
take a screenshot of the second monitor
rect = getRectAsImage(screens[1])
0 for the first display 1 for the second and ...
#saves screenshot
rect.save('leftscr.png',format='png')

Categories

Resources