1. 程式人生 > >如何利用Python和win32程式設計避免重複性體力勞動(三)——文字框操作:WM_GETTEXT 和WM_SETTEXT

如何利用Python和win32程式設計避免重複性體力勞動(三)——文字框操作:WM_GETTEXT 和WM_SETTEXT

請移步至這裡以獲得更加的排版和閱讀體驗,謝謝您

Part 3:控制元件操作A

通過選單的目錄操作,我們打開了開啟檔案對話方塊。為了簡單起見,我們可以直接在檔名處填入要開啟檔案的絕對路徑。怎麼填呢?

首先還是定位到文字框控制元件

handle = find_subHandle(Mhandle, [("ComboBoxEx32", 0), ("ComboBox", 0), ("Edit", 0)])

find_subHandle()是在Part 1中定義的函式,可以按照列表的資訊查詢Mhandle的子窗體。列表中的元組提供窗體的類名和排位號(z-index)。列表索引編號較小的為父窗體。

接著我們依然是利用win32的訊息機制,給這個文字框控制元件送去一個訊息:

win32api.SendMessage(handle, win32con.WM_SETTEXT, 0, os.path.abspath(fgFilePath).encode('gbk'))

在這裡,我們用了SendMessage而不是PostMessage,其區別就在於我們可以通過SendMessage取得訊息的返回資訊。因為對於我們要設定文字框資訊的WM_SETTEXT資訊來說,設定成功將返回True。

  • SendMessage(hWnd, Msg, wParam, lParam)

    • 描述:在訊息佇列中加入為指定的窗體加入一條訊息,直到窗體處理完資訊才返回。
    • 引數:
      • hWnd:整型,接收訊息的窗體控制代碼
      • Msg:整型,要傳送的訊息,這些訊息都是windows預先定義好的,可以參見系統定義訊息(System-Defined Messages).aspx#system_defined)
      • wParam:整型,訊息的wParam引數
      • lParam:整型,訊息的lParam引數
    • 說明:wParam和IParam根據具體的訊息不同而有不同的定義,詳情參閱Part 2.
  • WM_SETTEXT 訊息

    • 描述:設定窗體的文字
    • 引數:
      • wParam:未使用
      • lParam:一個指標,指向以null結尾的字串。窗體文字將被設定為該字串。
    • 返回值:
      • 如果成功設定,則返回1(MSDN原文是返回True)
    • 說明:
      • 上面的定義是直接從MSDN上翻譯過來的,在Python的語境裡面沒有指標,你只需要把變數名作為lParam傳入就好了。
      • 另外,請注意編碼,包含中文請用gbk編碼,否則亂碼

再利用一個WM_COMMAND訊息來點選確定按鈕:

win32api.SendMessage(Mhandle, win32con.WM_COMMAND, 1, confirmBTN_handle)
  • WM_COMMAND 訊息
    • 描述:當用戶選擇了選單(或按鈕等控制元件的)命令,或控制元件傳送通知到父視窗,或加速鍵擊(accelerator keystroke is translated)時傳送。
    • 引數:根據情景不同而不同,在這裡屬於使用者命令,引數配置如下
      • wParam:HIWORD為0(未使用),LOWORD為控制元件的ID
      • lParam:0(未使用)
    • 返回值:如果窗體處理了訊息,應返回0

綜上,我們現在就可以利用win32的各種API完成開啟fg檔案的任務了。

def open_fg(self, fgFilePath):
    """開啟fg檔案"""
    Mhandle, confirmBTN_handle = self.menu_command('open')
    handle = find_subHandle(Mhandle, [("ComboBoxEx32", 0), ("ComboBox", 0), ("Edit", 0)])
    if win32api.SendMessage(handle, win32con.WM_SETTEXT, 0, os.path.abspath(fgFilePath).encode('gbk')) == 1:
        return win32api.SendMessage(Mhandle, win32con.WM_COMMAND, 1, confirmBTN_handle)
    raise Exception("File opening path set failed")

順便,如果要獲取目標文字框的內容呢,可以使用WM_GETTEXT,如下:

  • WM_GETTEXT 訊息:
    • 描述:將窗體的文字內容複製到指定的buffer物件中
    • 引數:
      • wParam:要複製字元的最大長度,包括截尾的空位元組
      • lParam:用來儲存字串的buffer的指標
    • 返回值:返回複製字元的數量,不包括截尾的空位元組

利用win32gui.PyMakeBuffer(len, addr)可以造一個buffer物件,類似python3中的bytearray,lParam的返回值。而利用WM_GETTEXTLENGTH可以獲取不含截尾空位元組的文字長度的長度,可以用來設定Buffer的長度。完整的示例如下:

buf_size = win32gui.SendMessage(hwnd, win32con.WM_GETTEXTLENGTH, 0, 0) + 1  # 要加上截尾的位元組
str_buffer = win32gui.PyMakeBuffer(buf_size)  # 生成buffer物件
win32api.SendMessage(hwnd, win32con.WM_GETTEXT, buf_size, str_buffer)  # 獲取buffer
str = str(str_buffer[:-1])  # 轉為字串