2015-05-12 20 views
8

Tôi đang cố gắng viết một chương trình tìm thấy một cửa sổ bằng cách tìm kiếm tiêu đề của nó. Một khi nó đã tìm thấy cửa sổ, nó sẽ cố gắng để đưa nó lên phía trước. Tôi đang sử dụng API win32gui để đạt được điều này. Tôi có thể làm cho nó hoạt động được nhiều nhất, nhưng vì lý do nào đó nó không hoạt động nếu taskmanager ở phía trước. Tôi có mã mẫu sau.Python win32gui SetAsForegroundWindow chức năng không hoạt động đúng

import win32gui, win32con 
import re, traceback 
from time import sleep 

class cWindow: 
    def __init__(self): 
     self._hwnd = None 

    def BringToTop(self): 
     win32gui.BringWindowToTop(self._hwnd) 

    def SetAsForegroundWindow(self): 
     win32gui.SetForegroundWindow(self._hwnd) 

    def Maximize(self): 
     win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE) 

    def setActWin(self): 
     win32gui.SetActiveWindow(self._hwnd) 

    def _window_enum_callback(self, hwnd, wildcard): 
     '''Pass to win32gui.EnumWindows() to check all the opened windows''' 
     if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) != None: 
      self._hwnd = hwnd 

    def find_window_wildcard(self, wildcard): 
     self._hwnd = None 
     win32gui.EnumWindows(self._window_enum_callback, wildcard) 


def main(): 
    sleep(5) 
    try:  
     wildcard = ".*Building Operation WorkStation.*" 
     cW = cWindow() 
     cW.find_window_wildcard(wildcard) 
     cW.Maximize() 
     cW.BringToTop() 
     cW.SetAsForegroundWindow() 

    except: 
     f = open("log.txt", "w") 
     f.write(traceback.format_exc()) 
     print traceback.format_exc() 
main() 

Tôi đã ghép nối chúng với nhau từ nhiều nguồn trực tuyến. Nó có vẻ làm việc cho hầu hết các phần nhưng đối với một số cửa sổ như trình quản lý tác vụ, nó sẽ làm việc đôi khi nhưng không thành công. Khi nó không hoạt động đúng, tất cả những gì tôi thấy là biểu tượng ứng dụng nhấp nháy màu vàng. Có một cách thích hợp để làm điều này để đảm bảo rằng cửa sổ mà tôi quan tâm được thiết lập để foreground 100% số lần? Tôi không chắc chắn nếu điều này là có liên quan nhưng tôi đang sử dụng Windows 7 Professional (32-bit) với Gói Dịch vụ 1.

Trả lời

4

Tôi đã tìm thấy một giải pháp: nếu taskmanager, sau đó giết nó. Tôi đã thêm phương thức vào cWindow:

def kill_task_manager(self): 
    # Here I use your method to find a window because of an accent in my french OS, 
    # but you should use win32gui.FindWindow(None, 'Task Manager complete name'). 
    wildcard = 'Gestionnaire des t.+ches de Windows' 
    self.find_window_wildcard(wildcard) 
    if self._hwnd: 
     win32gui.PostMessage(self._hwnd, win32con.WM_CLOSE, 0, 0) # kill it 
     sleep(0.5) # important to let time for the window to be closed 

Gọi phương thức này ngay sau cW = cWindow().

bẫy

lỗi khác là để ngăn chặn ngoại lệ này trong SetAsForegroundWindow:

error: (0, 'SetForegroundWindow', 'No error message is available') 

chỉ cần gửi một phím alt trước khi cuộc gọi win32gui:

# Add this import 
import win32com.client 

# Add this to __ini__ 
self.shell = win32com.client.Dispatch("WScript.Shell") 

# And SetAsForegroundWindow becomes 
def SetAsForegroundWindow(self): 
    self.shell.SendKeys('%') 
    win32gui.SetForegroundWindow(self._hwnd) 

cuối, nếu tôi có thể, đừng so sánh != None nhưng is not None. pythonic hơn;)

Đây là mã đầy đủ:

# coding: utf-8 

import re, traceback 
import win32gui, win32con, win32com.client 
from time import sleep 


class cWindow: 
    def __init__(self): 
     self._hwnd = None 
     self.shell = win32com.client.Dispatch("WScript.Shell") 

    def BringToTop(self): 
     win32gui.BringWindowToTop(self._hwnd) 

    def SetAsForegroundWindow(self): 
     self.shell.SendKeys('%') 
     win32gui.SetForegroundWindow(self._hwnd) 

    def Maximize(self): 
     win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE) 

    def setActWin(self): 
     win32gui.SetActiveWindow(self._hwnd) 

    def _window_enum_callback(self, hwnd, wildcard): 
     '''Pass to win32gui.EnumWindows() to check all the opened windows''' 
     if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) is not None: 
      self._hwnd = hwnd 

    def find_window_wildcard(self, wildcard): 
     self._hwnd = None 
     win32gui.EnumWindows(self._window_enum_callback, wildcard) 

    def kill_task_manager(self): 
     wildcard = 'Gestionnaire des t.+ches de Windows' 
     self.find_window_wildcard(wildcard) 
     if self._hwnd: 
      win32gui.PostMessage(self._hwnd, win32con.WM_CLOSE, 0, 0) 
      sleep(0.5) 

def main(): 
    sleep(5) 
    try: 
     wildcard = ".*Building Operation WorkStation.*" 
     cW = cWindow() 
     cW.kill_task_manager() 
     cW.find_window_wildcard(wildcard) 
     cW.BringToTop() 
     cW.Maximize() 
     cW.SetAsForegroundWindow() 

    except: 
     f = open("log.txt", "w") 
     f.write(traceback.format_exc()) 
     print(traceback.format_exc()) 


if __name__ == '__main__': 
    main() 

Nguồn: how do I close window with handle using win32gui in Pythonwin32gui.SetActiveWindow() ERROR : The specified procedure could not be found.

5

Lưu ý: Sau đây giao dịch chỉ với đảm bảo rằng cửa sổ luôn-on-top như Task Manager được ẩn trước khi kích hoạt cửa sổ - nó giả định rằng phần kích hoạt bản thân hoạt động tốt, có thể không phải là trường hợp. Các điều kiện mà theo đó một quy trình được phép gọi hàm SetForegroundWindow Windows API được liệt kê here.


Task Manager là đặc biệt ở hai khía cạnh:

  • Theo mặc định, nó được thiết lập để hiển thị luôn luôn trên đầu, nghĩa là, trên tất cả các cửa sổ khác.
  • Ngay cả khi điều đó bị tắt (Options > Always on Topkiểm soát), bạn có thể vẫn làm cho nó hiển thị trên đầu trang của cửa sổ luôn-on-top khác (cái gì mà các cửa sổ thông thường dường như không thể làm được).

Mã của bạn:

  • làm việc - trong các thử nghiệm của tôi - theo nghĩa là cửa sổ mục tiêu không trở thành cửa sổ hoạt động.
  • không hoạt động theo nghĩa là cửa sổ Trình quản lý tác vụ vẫn ở trên đầu cửa sổ (phóng to).
    • thậm chí cố gắng thực hiện cửa sổ luôn luôn của bạn cũng sẽ không giúp ích gì.

Cụ thể kiểm tra sự hiện diện của các cửa sổ Task Manager và giảm thiểu nó là một lựa chọn, nhưng lưu ý rằng có thể có cửa sổ khác luôn-on-top, vì vậy kiếm một giải pháp mạnh mẽ bạn có để xác định tất cả các cửa sổ đang mở luôn-on-top và giảm thiểu chúng:

sau đây cố gắng hết sức để xác định tất cả các cửa sổ luôn-on-top trừ Task Bar và nút Start, và giảm thiểu (ẩn một cách hiệu quả s) bất kỳ cửa sổ nào như vậy.

Phương pháp mới là hide_always_on_top_windows_window_enum_callback_hide.

import win32gui, win32con 
import re, traceback 
from time import sleep 

class cWindow: 
    def __init__(self): 
     self._hwnd = None 

    def SetAsForegroundWindow(self): 
     # First, make sure all (other) always-on-top windows are hidden. 
     self.hide_always_on_top_windows() 
     win32gui.SetForegroundWindow(self._hwnd) 

    def Maximize(self): 
     win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE) 

    def _window_enum_callback(self, hwnd, regex): 
     '''Pass to win32gui.EnumWindows() to check all open windows''' 
     if self._hwnd is None and re.match(regex, str(win32gui.GetWindowText(hwnd))) is not None: 
      self._hwnd = hwnd 

    def find_window_regex(self, regex): 
     self._hwnd = None 
     win32gui.EnumWindows(self._window_enum_callback, regex) 

    def hide_always_on_top_windows(self): 
     win32gui.EnumWindows(self._window_enum_callback_hide, None) 

    def _window_enum_callback_hide(self, hwnd, unused): 
     if hwnd != self._hwnd: # ignore self 
      # Is the window visible and marked as an always-on-top (topmost) window? 
      if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) & win32con.WS_EX_TOPMOST: 
       # Ignore windows of class 'Button' (the Start button overlay) and 
       # 'Shell_TrayWnd' (the Task Bar). 
       className = win32gui.GetClassName(hwnd) 
       if not (className == 'Button' or className == 'Shell_TrayWnd'): 
        # Force-minimize the window. 
        # Fortunately, this seems to work even with windows that 
        # have no Minimize button. 
        # Note that if we tried to hide the window with SW_HIDE, 
        # it would disappear from the Task Bar as well. 
        win32gui.ShowWindow(hwnd, win32con.SW_FORCEMINIMIZE) 

def main(): 
    sleep(5) 
    try:  
     regex = ".*Building Operation WorkStation.*" 
     cW = cWindow() 
     cW.find_window_regex(regex) 
     cW.Maximize() 
     cW.SetAsForegroundWindow() 

    except: 
     f = open("log.txt", "w") 
     f.write(traceback.format_exc()) 
     print(traceback.format_exc()) 
main() 
+0

nên không này: 'win32gui.GetWindowLong (hwnd, win32con.GWL_EXSTYLE) & win32con.WS_EX_TOPMOST' được' win32gui.GetWindowLong (hwnd, win32con.GWL_EXSTYLE & win32con.WS_EX_TOPMOST) '? Bạn đang cố gắng để bit và chúng lại với nhau phải không? – IronManMark20

+0

@ IronManMark20: 'win32gui.GetWindowLong (hwnd, win32con.GWL_EXSTYLE)' trả về một trường bit, và '& win32con.WS_EX_TOPMOST' kiểm tra nếu một bit cụ thể được thiết lập. Những gì bạn đang làm có khả năng dẫn đến một cờ không hợp lệ được chuyển đến 'GetWindowLong'. – mklement0

+1

OK. Nó trông có vẻ sai. Cảm ơn. – IronManMark20

Các vấn đề liên quan