使用Python快速啟動多個PC客戶端

作為一枚游戲測試,日常工作的時候,經(jīng)常需要同時開著多個游戲賬號進行測試。

以Unity打包出來的PC客戶端為例,每次都需要雙擊運行exe程序,等著游戲啟動后,因為同時開著多個客戶端,所以還需要拖動客戶端,來調(diào)整游戲在屏幕上的位置,防止遮擋,方便查看。

操作流程差不多就像這樣子(本文用記事本來替代游戲客戶端):

這個操作其實還是挺繁瑣的,尤其你開了3個以上客戶端的時候,能不能將上邊的操作做成工具來自動完成呢?

首先我們分析下這個操作的流程

那接下來用Python各個擊破吧~

啟動游戲

啟動游戲只需要一句代碼~

subprocess.Popen(r"C:\Windows\system32\notepad.exe")

subprocess是Python自帶的子進程管理模塊,定義有數(shù)個創(chuàng)建子進程的函數(shù),也提供了一些管理標(biāo)準(zhǔn)流(standard stream)和管道(pipe)的工具,從而在進程間使用文本通信。簡單理解就是,通過CMD敲的命令,都基本可以用subprocess來實現(xiàn)批量處理。

計算客戶端的坐標(biāo)位置

基本思路:

  • 確認(rèn)游戲的窗口大小,如800*450
  • 計算整個屏幕大小,可以放多少個800*450的客戶端,并計算出每個客戶端的坐標(biāo)位置

如何獲取屏幕大小呢?Python在Windows平臺有一個庫叫pywin32,它為Python提供訪問Windows API的擴展,提供了齊全的Windows常量、接口、線程以及COM機制等。

安裝pywin32,在sourceforge下載對于你電腦Py版本的exe安裝包,直接運行即可。

pywin32提供了一個方法win32gui.GetClientRect,可以獲取窗口坐標(biāo)及大小,只需要將桌面窗口句柄作為參數(shù)傳進去即可。

所以獲取桌面分辨率的方式就是:

_, _, width, height = win32gui.GetClientRect(win32gui.GetDesktopWindow())

接下來就是計算在桌面上,可以擺放多少個游戲客戶端了,就像下圖這個樣子。

這個不復(fù)雜,就直接上代碼了,計算出桌面可以擺放的客戶端的左上角坐標(biāo),保存到一個列表里邊備用

game_width = 450
game_height = 800

_, _, width, height = win32gui.GetClientRect(win32gui.GetDesktopWindow())

x_num = int(width / game_width)
y_num = int(height / game_height)

result = list()

for y in range(y_num):
    for x in range(x_num):
        result.append((x * game_width, y * game_height, game_width, game_height))

print(result)

output: [(0, 0, 450, 800), (450, 0, 450, 800), (900, 0, 450, 800), (1350, 0, 450, 800)]

調(diào)整窗口大小并拖動到指定位置


win32gui.MoveWindow(hwnd, x, y, width, height, bRepaint) 提供了一個移動窗口的方式,函數(shù)的幾個參數(shù)分別表示句柄,起始點x坐標(biāo),y坐標(biāo),寬度,高度,是否重繪界面。

app_pid = subprocess.Popen(r"C:\Windows\system32\notepad.exe").pid  # 獲取進程pid
time.sleep(1)
hwnd_list = []
win32gui.EnumWindows(lambda _hwnd, _hwnd_list: _hwnd_list.append(_hwnd), hwnd_list)  # 獲取當(dāng)前全部的窗口句柄
app_hwnd = None
for hwnd in hwnd_list:
    hid, pid = win32process.GetWindowThreadProcessId(hwnd)  # 根據(jù)窗口句柄取出窗口的hid和pid
    if pid == app_pid:
        app_hwnd = hwnd
        break
if not app_hwnd:
    raise Exception("沒有找到hwnd")

app_position = result.pop(0)
win32gui.MoveWindow(app_hwnd, *app_position, True)  # 移動窗口位置

再封裝下


import win32gui
import win32process
import subprocess
import time


def calculate_app_positions(app_width, app_height, scale):
    _, _, width, height = win32gui.GetClientRect(win32gui.GetDesktopWindow())
    final_app_width = int(app_width * scale)
    final_app_height = int(app_height * scale)
    x_num = int(width / final_app_width)
    y_num = int(height / final_app_height)

    positions = list()

    for y in range(y_num):
        for x in range(x_num):
            positions.append((x * final_app_width, y * final_app_height, final_app_width, final_app_height))
    return positions


def start_app(app_path, num, app_width, app_height, scale):
    app_positions = calculate_app_positions(app_width, app_height, scale)
    for i in range(num):
        app_pid = subprocess.Popen(app_path).pid  # 獲取進程pid
        time.sleep(1)
        hwnd_list = []
        win32gui.EnumWindows(lambda _hwnd, _hwnd_list: _hwnd_list.append(_hwnd), hwnd_list)  # 獲取當(dāng)前全部的窗口句柄
        app_hwnd = None
        for hwnd in hwnd_list:
            hid, pid = win32process.GetWindowThreadProcessId(hwnd)  # 根據(jù)窗口句柄取出窗口的hid和pid
            if pid == app_pid:
                app_hwnd = hwnd
                break
        if not app_hwnd:
            raise Exception("沒有找到hwnd")

        app_position = app_positions.pop(0)
        win32gui.MoveWindow(app_hwnd, *app_position, True)  # 移動窗口位置


if __name__ == '__main__':

    app_path = r"C:\Windows\system32\notepad.exe"
    app_width = 450
    app_height = 800

    result = input("輸入要打開的客戶端數(shù)量和顯示比例,默認(rèn)比例是1.0,例子:3 0.75\n")
    result = result.split()
    if len(result) == 2:
        num, scale = result
    else:
        num = result[0]
        scale = 1
    start_app(app_path, int(num), app_width, app_height, float(scale))

最終運行效果~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容