def enum_windows_cb(hwnd, lparam): if not IsWindowVisible(hwnd): log("window %#x is not visible", hwnd) return True pid = c_ulong() thread_id = GetWindowThreadProcessId(hwnd, byref(pid)) if pid==ourpid: log("skipped our own window %#x, thread id=%#x", hwnd, thread_id) return True rect = RECT() if GetWindowRect(hwnd, byref(rect))==0: log("GetWindowRect failure") return True if hwnd==taskbar: log("skipped taskbar") return True #skipping IsWindowEnabled check length = GetWindowTextLengthW(hwnd) buf = create_unicode_buffer(length+1) if GetWindowTextW(hwnd, buf, length+1)>0: window_title = buf.value else: window_title = '' left, top, right, bottom = rect.left, rect.top, rect.right, rect.bottom w = right-left h = bottom-top if left<=-32000 or top<=-32000: log("%r is not visible: %s", window_title, (left, top, w, h)) if w<=0 and h<=0: log("skipped invalid window size: %ix%i", w, h) return True windows[hwnd] = (window_title, (left, top, w, h)) return True
def get_owner_info(owner, our_window): if not owner: return "unknown" if owner==our_window: return "our window (hwnd=%#x)" % our_window pid = DWORD(0) GetWindowThreadProcessId(owner, byref(pid)) if not pid: return "unknown (hwnd=%#x)" % owner #log("get_owner_info(%#x) pid=%s", owner, pid.value) proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid) if not proc_handle: return "pid %i (hwnd=%#x)" % (pid.value, owner) try: size = DWORD(256) process_name = create_string_buffer(size.value+1) if not QueryFullProcessImageNameA(proc_handle, 0, process_name, byref(size)): return "pid %i" % pid.value return "'%s' with pid %s (hwnd=%#x)" % (bytestostr(process_name.value), pid.value, owner) finally: CloseHandle(proc_handle)
def enum_windows_cb(hwnd, lparam): if not IsWindowVisible(hwnd): l("skipped invisible window %#x", hwnd) return True pid = c_int() thread_id = GetWindowThreadProcessId(hwnd, byref(pid)) if pid == ourpid: l("skipped our own window %#x", hwnd) return True #skipping IsWindowEnabled check length = GetWindowTextLengthW(hwnd) buf = create_unicode_buffer(length + 1) if GetWindowTextW(hwnd, buf, length + 1) > 0: window_title = buf.value else: window_title = '' l( "get_shape_rectangles() found window '%s' with pid=%i and thread id=%i", window_title, pid, thread_id) rect = RECT() if GetWindowRect(hwnd, byref(rect)) == 0: l("GetWindowRect failure") return True left, top, right, bottom = rect.left, rect.top, rect.right, rect.bottom if right < 0 or bottom < 0: l("skipped offscreen window at %ix%i", right, bottom) return True if hwnd == taskbar: l("skipped taskbar") return True #dirty way: if window_title == 'Program Manager': return True #this should be the proper way using GetTitleBarInfo (but does not seem to work) #import ctypes #from ctypes.windll.user32 import GetTitleBarInfo #@UnresolvedImport #from ctypes.wintypes import (DWORD, RECT) #class TITLEBARINFO(ctypes.Structure): # pass #TITLEBARINFO._fields_ = [ # ('cbSize', DWORD), # ('rcTitleBar', RECT), # ('rgstate', DWORD * 6), #] #ti = TITLEBARINFO() #ti.cbSize = sizeof(ti) #GetTitleBarInfo(hwnd, byref(ti)) #if ti.rgstate[0] & win32con.STATE_SYSTEM_INVISIBLE: # log("skipped system invisible window") # return True w = right - left h = bottom - top l("shape(%s - %#x)=%s", window_title, hwnd, (left, top, w, h)) if w <= 0 and h <= 0: l("skipped invalid window size: %ix%i", w, h) return True if left == -32000 and top == -32000: #there must be a better way of skipping those - I haven't found it l("skipped special window") return True #now clip rectangle: if left < 0: left = 0 w = right if top < 0: top = 0 h = bottom rectangles.append((left, top, w, h)) return True
def get_layout_spec(self): KMASKS = (0xffffffff, 0xffff, 0x3ff) layout = None layouts = [] variant = None variants = None options = "" layout_code = 0 try: l = _GetKeyboardLayoutList() log("GetKeyboardLayoutList()=%s", csv(hex(v) for v in l)) for hkl in l: for mask in KMASKS: kbid = hkl & mask if kbid in WIN32_LAYOUTS: code, _, _, _, _layout, _variants = WIN32_LAYOUTS.get( kbid) log( "found keyboard layout '%s' / %#x with variants=%s, code '%s' for kbid=%i (%#x)", _layout, kbid, _variants, code, kbid, hkl) if _layout not in layouts: layouts.append(_layout) if not layout_code: layout_code = kbid break except Exception as e: log.error("Error: failed to detect keyboard layouts:") log.error(" %s", e) try: pid = DWORD(0) GetWindowThreadProcessId(0, byref(pid)) tid = GetWindowThreadProcessId(0, pid) hkl = GetKeyboardLayout(tid) log("GetKeyboardLayout(%i)=%#x", tid, hkl) for mask in KMASKS: kbid = hkl & mask if kbid not in WIN32_LAYOUTS: continue code, _, _, _, layout0, variants = WIN32_LAYOUTS.get(kbid) log( "found keyboard layout '%s' / %#x with variants=%s, code '%s' for kbid=%i (%#x)", layout0, kbid, variants, code, kbid, hkl) if layout0 not in layouts: layouts.append(layout0) #only override "layout" if unset: if not layout and layout0: layout = layout0 layout_code = kbid except Exception: log.error("Error: failed to detect keyboard layout", exc_info=True) KL_NAMELENGTH = 9 name_buf = create_string_buffer(KL_NAMELENGTH) if GetKeyboardLayoutName(name_buf): log("get_layout_spec() GetKeyboardLayoutName()=%s", bytestostr(name_buf.value)) try: #win32 API returns a hex string ival = int(name_buf.value, 16) except ValueError: log.warn("Warning: failed to parse keyboard layout code '%s'", bytestostr(name_buf.value)) else: sublang = (ival & 0xfc00) >> 10 log("sublang(%#x)=%#x", ival, sublang) for mask in KMASKS: val = ival & mask kbdef = WIN32_KEYBOARDS.get(val) log("get_layout_spec() WIN32_KEYBOARDS[%#x]=%s", val, kbdef) if kbdef: _layout, descr = kbdef if _layout == "??": log.warn( "Warning: the X11 codename for %#x is not known", val) log.warn(" only identified as '%s'", descr) log.warn(" please file a bug report") continue elif not layout: layout = _layout layout_code = val break if not layout: log.warn("Warning: unknown keyboard layout %#x", ival) log.warn(" please file a bug report") self.last_layout_message = layout if layouts and not layout: layout = layouts[0] if layout and self.last_layout_message != layout: log.info("keyboard layout code %#x", layout_code) log.info("identified as '%s' : %s", descr, layout) self.last_layout_message = layout return layout, layouts, variant, variants, options