I've been looking into using the wx python package on Windows 7. Specifically, I would like to be able to get the image data of a existing window (i.e. not a window opened by the python program). It appears I can do this by getting the window's device context, creating a compatible device context, copying the bitmap, and then using it how I like from there. The problem is that I can't seem to find the way to get the device context (or the handle) of an existing window. I only see ways to get them from windows the python program using wx created. How might I be able to go about doing this? Thank you much!
wx may not have a way to do this.
The Windows APIs you need are pretty simple, and you can use them through win32api (or ctypes if you prefer, but that's a lot more work).
First, I don't know how you're planning to identify the window you want. If you have its class and name, you can just FindWindow (or, if it may not be a top-level window, FindWindowEx). If you want to search by something else, you will probably need to call EnumWindow (plus EnumChildWindows recursively, if you're not sure it's a top-level window).
At this point, you can just call wx.Windows.AssociateHandle to attach a wx.Window object to the HWND.
If you can't do that for whatever reason, GetDC gives you a display context for an HWND. You can then create a memory DC, or get the DC for the native window under underlying your wx window, and BitBlt from one to the other.
Just to expand on the other answer, try this code (untested, I'm not on Windows right now)...
# first use FindWindow or FindWindowEx to determine window handle
frame = wx.Frame(None)
frame.AssociateHandle(handle)
dc = wx.ClientDC(frame)
width, height = dc.GetSize()
bitmap = wx.EmptyBitmap(width, height)
mdc = wx.MemoryDC(bitmap)
mdc.Blit(0, 0, width, height, dc, 0, 0)
del mdc
bitmap.SaveFile('output.png', wx.BITMAP_TYPE_PNG)
Related
I want to be able to change the windows mouse cursors into a custom one (with the .ani or .cur extention) globally using a python script. Is there any package or module that can help me accomplish this?
It cannot be done globally, since it would break a security constraints. Application is not allowed modify anything over other applications or system windows.
It can be done by system C API only by processes run by root/administrator. Probably no one made a Python bindings for such functions. It is possible, but due to limited use I don't think there is any Python module doing that.
you can use your own image as the mouse cursor. Use pyglet.image.load to load the image, then create an ImageMouseCursor with the image and "hot-spot" of the cursor. The hot-spot is the point of the image that corresponds to the actual pointer location on screen, for example, the point of the arrow:
image = pyglet.image.load('cursor.png')
cursor = pyglet.window.ImageMouseCursor(image, 16, 8)
window.set_mouse_cursor(cursor)
You can even render a mouse cursor directly with OpenGL. You could draw a 3-dimensional cursor, or a particle trail, for example. To do this, subclass MouseCursor and implement your own draw method. The draw method will be called with the default pyglet window projection, even if you are using another projection in the rest of your application.
Yes (in windows), in windows: you need to change a registry key, then tell windows to load new cursor.
This code does the trick:
import os
import ctypes
path = r"HKEY_CURRENT_USER\Control Panel\Cursors"
cur_loc = r"path\to\cursor.cur"
os.system(f"""REG ADD "{path}" /v Arrow /t REG_EXPAND_SZ /d "{cur_loc}" /f""")
ctypes.windll.user32.SystemParametersInfoA(0x57)
I am new to python and want to learn this from the basic.
I want to open two other application like notepad in a single window. I searched for any examples by using "tkinter". Any idea for implementing this using "tkinter".
PS: two tabs one in left and one in right so that one tab will be having notepad and other will have a media player (let say) and i should be able to close the single parent window for closing this child windows.
On Unix systems with X server the XEmbed protocol exists for such purpose, but it requires the child application to be specifically prepared for that (here's a related question).
On Windows this can be accomplished using the Win32 API. You have to get the handles of the parent and child windows and use the SetParent function.
Here's a proof of concept:
from tkinter import Tk
from win32gui import SetParent, FindWindow, SetWindowPos
import time
import subprocess
def attach_window(window_class, parent, x, y, width, height):
child = FindWindow(window_class, None)
SetParent(child, parent)
SetWindowPos(child, 0, x, y, width, height, 0)
def main():
root = Tk()
subprocess.Popen('C:\\Windows\\system32\\notepad.exe')
subprocess.Popen('C:\\Windows\\system32\\calc.exe')
# Give child processes enough time to launch
time.sleep(0.5)
# Get the HWND of the parent window
parent = int(root.frame(), 16)
attach_window('Notepad', parent, 0, 0, 400, 200)
attach_window('CalcFrame', parent, 0, 205, 420, 320)
root.geometry('500x500')
root.mainloop()
if __name__ == '__main__':
main()
Keep in mind that you have to install PyWin32 for this to work.
I don't think you will be able to do this easily. Notepad is using its own toolkit which, most probably, is not compatible with the one you are using.
If you want to open eg. an editor, look for a widget in the toolkit of your choice which does what you want (or nearly). Eg. if you want an editor, use the GtkTextView in GTK, or, if you want something that can do code editing, look at GtkSourceView, etc. Same goes for media applications.
The 'include' applications as part of a project works only to a certain point. You can eg, include text-mode applications in a terminal window, but graphical apps are much harder.
For what you need, you will have to use libraries like tkinter or pyqt. As you want to learn it from the basic, I would suggest you to pick a GUI library and start learning it. Eventually you will know how to get the result that you desire.
I'm a bit confused with some gtk and gnome concepts. I'm trying to get list of non minimized windows on my gnome2 desktop, but after reading the pygtk documentation and inspecting the results, I can't understand the results.
Neither of the two snippets below appears to work.
First I tried this..
>>> gtk.gdk.window_get_toplevels()
[<gtk.gdk.Window object at 0xb74339b4 (GdkWindow at 0x8a4c170)>]
>>> gtk.gdk.window_get_toplevels()[0].get_children()
[]
then this
>>> d = gtk.gdk.DisplayManager()
>>> d.get_default_display().get_screen(0).get_root_window().get_children()
[<gtk.gdk.Window object at 0x89dcc84 (GdkWindow at 0x8a4c170)>, <gtk.gdk.Window object at 0x89dccac (GdkWindow at 0x8a4c0c0)>]
As seen in the console output, the second option returns two windows. But I haven't been able to figure out what they are. None of them has any children and I allways get those two windows regardless how many windows I have on my desktop.
Could anybody explain the hierarchy of objects of the typical gtk based desktop environment?
I can't understand why the above code doesn't work.
Please refrain from posting alternative solutions that resource to wnck, xlib, qt, etc. I'm more interested in understanding what I am doing wrong than in getting advice such us checking other libraries.
Your constraint is like saying "I want to build a CD player using only a banana. Please refrain from posting alternative solutions that resort to lasers." GTK can't do that, you're using the wrong tool for the job.
Here's an explanation of what a "window" actually means and why your code doesn't work:
First off, you need to understand the difference between a gtk.Window and a gtk.gdk.Window. A GTK window is a top level GTK widget that can contain other widgets. It is usually linked to a window on your desktop, but doesn't have to be - in GTK 3 there is an OffscreenWindow.
A GDK window, on the other hand, is platform-dependent. On an X desktop it is a thin wrapper around an X window, which is not necessarily a toplevel desktop window. On other systems it exists to abstract away the windowing system. A GDK window receives events, so some GTK non-window widgets have their own GDK windows. "Window" is really a terrible name for these objects, but it was inherited from X and it's probably not going to change.
Each GTK process only knows about its own windows. You can get a list of the toplevel GTK windows of your own application using gtk.window_list_toplevels(). Getting the children of these windows should return you the GTK widgets that they contain. However, you can't descend into the widget hierarchy of other processes' windows. For example, what if another process has a window with a child widget that is a custom widget that your process doesn't know about? What should it report as the type of that widget?
Getting a list of the toplevel GDK windows with gtk.gdk.window_get_toplevels() is basically the same as getting a list of the toplevel X windows, as far as I understand it. You have no way of knowing what kind of windows they are - they might be the Gnome Panel, or they might be Qt windows, or they might be something else altogether that doesn't correspond with a desktop window.
Libwnck (link to the overview of what it does) can get you a list of non-minimized windows, and their titles, but it won't allow you to see inside them. There's no way to do that. Libwnck uses GDK internally, so technically you could do it using GDK, but why would you bother if there's already a library that does that for you? If you really want to do it yourself, look at the libwnck source code.
The windows you get are the windows that were created within your process. To get the list of windows, you need to query the properties of the root window, like this:
import gtk.gdk
root = gtk.gdk.get_default_root_window()
for id in root.property_get('_NET_CLIENT_LIST')[2]:
w = gtk.gdk.window_foreign_new(id)
if w:
print(w.property_get('WM_NAME')[2])
Please note that GDK is a thin layer over underlying OS graphics engine (X11/Quartz/Aqua/GDI etc) and result may differ on different NIX devices.
I am trying to rebuild the functionality of the desktop's "highlight to select" feature so that I can use it in my own app. When I say "highlight to select" I mean the selection box that shows up if you click and drag on your desktop (native to all main-stream OS).
I've been working for hours trying to recreate it, and simply can't find a way. I've tried PyGTK, Xlib for python, and a couple other weird hacks. All of which have their own problems that won't allow me to move forward.
I generally don't ask for straight up example code without providing some sort of starting point, but in this project I don't even know where to start. How would you do this?
Here's the requirements:
Must draw on the root window (or a transparent layer that "appears" to be the root)
Must return the coordinates of the selection (x, y, height width)
Update: Forgot some details.
I am using Ubuntu 10.10
I have dual monitors (though, I don't think that should matter)
I don't mind downloading any extra libraries that are necessary
I don't know if this is what you're looking for, but what if you created another window in your module, and have your code show it when you release drag? You could fetch the cursor's current position, and have it draw the window there.
This should help you get the mouse position on the root window.
So, your code may look a little like this (this is untested code!) I'm only showing the relevant portions of what goes inside __ init __.
def __init__(self):
...
#Some of your code here.
...
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
#Note that I am creating a popup window separately.
popwin = gtk.Window(gtk.WINDOW_POPUP)
#I am setting "decorated" to False, so it will have no titlebar or window controls.
#Be sure to compensate for this by having another means of closing it.
popwin.set_decorated(False)
def ShowPopup():
#You may need to put additional arguments in above if this is to be an event.
#For sake of example, I'm leaving this open ended.
#Get the cursor position.
rootwin = widget.get_screen().get_root_window()
curx, cury, mods = rootwin.get_pointer()
#Set the popup window position.
popwin.move(curx, cury)
popwin.show()
def HidePopup():
#This is just an example for how to hide the popup when you're done with it.
popwin.hide()
...
#More of your code here.
...
#Of course, here is the code showing your program's main window automatically.
win.show()
A very simplistic approach, but it should give the appearance of what you're wanting.
I can get what I think is the Nautilus desktop window by using this code:
screen = wnck.screen_get_default()
while gtk.events_pending():
gtk.main_iteration()
for window in screen.get_windows():
if window.get_name() == 'x-nautilus-desktop':
xid = window.get_xid()
wrapped_window = gtk.gdk.window_foreign_new(xid)
but when I try to do wrapped_window.add() I get the error that the Window Object does not have the add method.
I know this can be done since someone already has a youtube video demoing the effect at http://www.youtube.com/watch?v=NOlIfhXQX9g but I can't figure out how to get the background window and put a widget on it.
Anyone know how to do it?
You're mixing up gtk.Window and gtk.gdk.Window. They are not the same. The former is a toplevel desktop window and functions as a container for GTK widgets; the latter is an abstraction of an area of the screen which can be drawn on top of, and is not a container.
You can't get an application's GTK widgets using libwnck. How to achieve the effect you want I don't know, but I think you need to look more into extending the window manager, since that is what manages the desktop.