Tom Gur <[EMAIL PROTECTED]> wrote: > I was wondering how do I get control over a window (Win32). > to be more specific, I need to find a handle to a window of a certain > program and minimize the window. >
Here's a function which returns a list of all windows where the class is 'PuTTY' or the title contains a particular string: from win32gui import EnumWindows, GetClassName, EnumChildWindows from win32ui import CreateWindowFromHandle, MessageBox def toplevelWindows(): res = [] def callback(hwnd, arg): name = GetClassName(hwnd) w = CreateWindowFromHandle(hwnd) title = w.GetWindowText() if "'s password:" in title or name=='PuTTY': res.append(w) EnumWindows(callback, 0) return res You can minimize a window once you have found it by calling ShowWindow (or SetWindowPlacement). If you don't want to depend on Python's win32 extensions being installed then you can also do the same thing using ctypes. In either case be very careful that you are only picking up the windows you wanted to find as enumerating top level windows will return a lot of hidden windows and if you start messing with these you will probably need to reboot your system. Here's something adapted from some stuff where I was playing with ctypes (so you could probably cut out a lot of crud). It's a complete program which will find a Firefox window with a specified string in the title and minimize it (without the test for the classname it will also minimize the command window you run it from). --------- minimize.py ------------- # # Minimize a specified window. # import sys import ctypes from ctypes import * def _stdcall(dllname, restype, funcname, *argtypes): # a decorator for a generator. # The decorator loads the specified dll, retrieves the # function with the specified name, set its restype and argtypes, # it then invokes the generator which must yield twice: the first # time it should yield the argument tuple to be passed to the dll # function (and the yield returns the result of the call). # It should then yield the result to be returned from the # function call. def decorate(func): api = getattr(WinDLL(dllname), funcname) api.restype = restype api.argtypes = argtypes def decorated(*args, **kw): iterator = func(*args, **kw) nargs = iterator.next() if not isinstance(nargs, tuple): nargs = (nargs,) try: res = api(*nargs) except Exception, e: return iterator.throw(e) return iterator.send(res) return decorated return decorate from ctypes.wintypes import HWND #, RECT, POINT LPARAM = c_ulong class metaENUM(type(ctypes.c_int)): def __init__(cls, name, bases, namespace): '''Convert enumeration names into attributes''' names = namespace.get('_names_', {}) if hasattr(names, 'keys'): for (k,v) in names.items(): setattr(cls, k, cls(v)) names[v]=k else: for (i,k) in enumerate(names): setattr(cls, k, cls(i)) super(metaENUM, cls).__init__(name, bases, namespace) class ENUM(ctypes.c_int): '''Enumeration base class. Set _names_ attribute to a list of enumeration names (counting from 0) or a dictionary of name:value pairs.''' __metaclass__ = metaENUM def __str__(self): return self.__repr__(fmt="%(value)s") def __repr__(self, fmt="<%(name)s %(value)s>"): try: return self._names_[self.value] except: return fmt % dict(name=self.__class__.__name__, value=self.value) def __int__(self): return self.value class BITMASK(ENUM): '''Some Microsoft 'enums' are actually bitmasks with several bits or'd together''' def __repr__(self, fmt="<%(name)s %(value)s>"): v = self.value values = [] while v: bit = v&(~v+1) try: values.append(self._names_[bit]) except (KeyError, IndexError): values.append(fmt % dict(name=self.__class__.__name__, value=self.value)) v &= ~bit if not values: return '0' return '|'.join(values) def __or__(self, other): return type(self)(int(self.value)|int(other.value)) class SHOWCMD(ENUM): _names_ = '''SW_HIDE SW_NORMAL SW_SHOW_MINIMIZED SW_SHOW_MAXIMIZED SW_SHOW_NOACTIVATE SW_SHOW SW_MINIMIZE SW_SHOWMINNOACTIVE SW_SHOWNA SW_RESTORE SW_SHOWDEFAULT SW_FORCEMINIMIZE'''.split() class WindowPlacementFlags(BITMASK): _names_ = dict(WPF_SETMINPOSITION = 1, WPF_RESTORETOMAXIMIZED = 2, WPF_ASYNCWINDOWPLACEMENT = 4) class Structure(ctypes.Structure): """As ctypes Structure but with added repr and comparison testing""" def __repr__(self): return "%s(%s)" % (self.__class__.__name__, ", ".join("%s=%r" % (f, getattr(self, f)) for (f,t) in self._fields_)) def __eq__(self, other): if self._fields_ != other._fields_: return False for (f,t) in self._fields_: if getattr(self,f) != getattr(other,f): return False return True class RECT(Structure): _fields_ = [("left", c_long), ("top", c_long), ("right", c_long), ("bottom", c_long)] class POINT(Structure): _fields_ = [("x", c_long), ("y", c_long)] class StructureWithLength(Structure): _fields_ = [('length', ctypes.c_ulong)] def __init__(self): ctypes.Structure.__init__(self) self.length = ctypes.sizeof(self) class WINDOWPLACEMENT(StructureWithLength): _fields_ = [ ('flags', WindowPlacementFlags), ('showCmd', SHOWCMD), ('ptMinPosition', POINT), ('ptMaxPosition', POINT), ('rcNormalPosition', RECT), ] def nonzero(result): # If the result is zero, and GetLastError() returns a non-zero # error code, raise a WindowsError if result == 0 and GetLastError(): raise WinError() return result WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_int, HWND, LPARAM) @ _stdcall("user32", c_int, "EnumWindows", WNDENUMPROC, LPARAM) def EnumWindows(callback, lparam=0): yield nonzero((yield WNDENUMPROC(callback), lparam)) @ _stdcall("user32", c_int, "GetWindowTextLengthW", HWND) def GetWindowTextLength(hwnd): yield nonzero((yield hwnd,)) @ _stdcall("user32", c_int, "GetWindowTextW", HWND, c_wchar_p, c_int) def GetWindowText(hwnd): len = GetWindowTextLength(hwnd)+1 buf = create_unicode_buffer(len) nonzero((yield hwnd, buf, len)) yield buf.value @ _stdcall("user32", c_int, "GetClassNameW", HWND, c_wchar_p, c_int) def GetClassName(hwnd): len = 256 buf = create_unicode_buffer(len) nonzero((yield hwnd, buf, len)) yield buf.value @ _stdcall("user32", c_int, "GetWindowRect", HWND, POINTER(RECT)) def GetWindowRect(hwnd): buf = RECT() nonzero((yield hwnd, buf)) yield buf @ _stdcall("user32", c_int, "GetClientRect", HWND, POINTER(RECT)) def GetClientRect(hwnd): buf = RECT() nonzero((yield hwnd, buf)) yield buf @ _stdcall("user32", c_int, "GetWindowPlacement", HWND, POINTER(WINDOWPLACEMENT)) def GetWindowPlacement(hwnd): buf = WINDOWPLACEMENT() nonzero((yield hwnd, buf)) yield buf @ _stdcall("user32", c_int, "SetWindowPlacement", HWND, POINTER(WINDOWPLACEMENT)) def SetWindowPlacement(hwnd, placement): yield nonzero((yield hwnd, placement)) @ _stdcall("user32", c_int, "IsWindow", HWND) def IsWindow(hwnd): yield bool((yield hwnd,)) @ _stdcall("user32", c_int, "ShowWindow", HWND, SHOWCMD) def ShowWindow(hwnd, showcmd): yield bool((yield hwnd,showcmd)) def toplevelWindows(): res = [] def callback(hwnd, arg): res.append(hwnd) return True EnumWindows(callback, 0) return res def iterWindows(klass, match): for hwnd in toplevelWindows(): if IsWindow(hwnd): try: title = GetWindowText(hwnd) except WindowsError, e: continue if klass==GetClassName(hwnd) and match in title: yield hwnd if __name__=='__main__': for hwnd in iterWindows("MozillaUIWindowClass", sys.argv[1]): wp = GetWindowPlacement(hwnd) ShowWindow(hwnd, SHOWCMD.SW_MINIMIZE) else: print "Sorry, I couldn't find the window" ----------------------------------- -- http://mail.python.org/mailman/listinfo/python-list