windows 10, 如何使用 batch , vbs 將桌面上的視窗移至特定位置?
這些腳本語言缺乏直接控制 Windows GUI 視窗 API(如 MoveWindow)的能力。
powershell 腳本過於複雜,有其它方法嗎?
如果您覺得 PowerShell 的寫法太複雜,希望有更直覺、程式碼更短的方法,最標準的解決方案是使用第三方小工具。
我們可以使用 Windows 社群中最著名的開源命令列視窗控制工具:Cmdow 或 NirCmd。下載後,您只需要在 Batch (
.bat) 裡面寫一行指令就能精準移動視窗。以下是這兩種最簡單的方法:
方法一:使用 Cmdow(最推薦,語法最直覺)
cmdow 是一個專門用來管理 Windows 視窗的免費命令列工具(僅約 30KB)。- 下載:前往官方或 GitHub 下載
cmdow.exe。 - 編寫 Batch:將
cmdow.exe跟您的.bat檔放在同一個資料夾,寫下這行指令:
- 優點:指令極短,直接指定「視窗標題」和「位置大小」即可。
方法二:使用 NirCmd(功能最強大的萬用工具)
NirCmd 是老牌系統微調工具,它同樣支援一行指令移動視窗。- 下載:前往 NirSoft 官網下載
nircmd.exe。 - 編寫 Batch:將
nircmd.exe與.bat放在一起,寫入以下指令:
- 延伸玩法:如果您想把視窗「置中」,它甚至支援
nircmd win center title "視窗標題"。
方法三:如果您堅持「不下載任何檔案」的純 VBScript 法
如果您因為公司資安規定不能下載任何 exe 執行檔,也不想用複雜的 PowerShell,那纯 VBScript 唯一的簡單做法是透過模擬鍵盤,將視窗直接最大化或最小化(無法指定精確的 X, Y 座標,但程式碼只有 4 行):
建立
maximize.vbs:(如果要最小化,請將最後一行的
x 改為 n)如果您想試試看第三方工具的方法,可以告訴我:
- 您是否允許在電腦下載/放置
cmdow.exe或nircmd.exe這些綠色免安裝小工具? - 您的目標視窗標題是否固定?(例如每次打開都叫同一個名字?)
我可以提供您直接打包好的檔案下載路徑與完整寫法。
不要執行檔。給我一個 vc6 可以執行的 C 程式
如果您不想下載外部執行檔,使用 VC6(Visual C++ 6.0)編寫一個簡單的 C 語言程式,直接呼叫 Windows API 絕對是最精準且程式碼最乾淨的方法。
VC6 雖然古老,但它內建的
windows.h 完全支援 FindWindow 和 MoveWindow 這兩個標準 API。C 語言原始碼
請在 VC6 中建立一個 Win32 Console Application(主控台應用程式),並將以下程式碼貼入您的
.c 檔案中:在 VC6 中的編譯與使用步驟
- 打開 VC6,點選功能表的 File -> New。
- 切換到 Projects 標籤,選擇 Win32 Console Application。
- 輸入專案名稱(例如
MoveWin),點選 OK,接著選擇 An empty project 後點 Finish。 - 再次點選 File -> New,切換到 Files 標籤,選擇 C++ Source File(檔名輸入
main.c,副檔名用.c即可)。 - 將上面的程式碼貼入,修改
windowTitle為您目前桌面上正開啟的視窗名稱。 - 按下鍵盤 F7(Build)進行編譯,再按下 Ctrl + F5(Execute)執行。
如果您的目標視窗標題會變動,請告訴我:
- 該視窗的標題是否包含動態字串?(例如瀏覽器分頁名稱會一直變)
- 您是否需要改用處理程序名稱(如
notepad.exe)來抓取視窗?
我可以幫您修改程式碼,改用
EnumWindows API 來進行模糊搜尋。如何找出桌面上所有視窗的 title?
在 C 語言中,要找出桌面上所有可見視窗的標題,不能只用
FindWindow,必須使用 EnumWindows API 來遍歷(列舉)系統中的所有頂層視窗。以下是可以在 VC6(Visual C++ 6.0)中直接編譯並執行的 C 程式碼。
C 語言原始碼
請在 VC6 的
.c 檔案中貼入以下程式碼:程式碼關鍵解析(為什麼這樣寫?)
EnumWindows:這個 API 會從畫面的最上層開始,把每一個視窗的「控制代碼(HWND)」輪流丟給EnumWindowsProc處理。IsWindowVisible:Windows 系統後台有無數個看不見的隱藏視窗(例如事件監聽、系統服務)。加上此判斷,可以確保只抓到你肉眼在桌面上看得到的視窗。GetWindowText:用來把視窗的HWND轉換成人類看得懂的 String(標題字串)。
如果您觀察輸出結果,可以告訴我:
- 您的目標視窗是否成功出現在列表上?
- 您接下來是否想把這個功能與上一步結合,寫成「輸入部分關鍵字,就自動移動該視窗」的自動化程式?
承上,如何知道 各 windows 本身的程式名稱?
要從視窗控制代碼(
HWND)取得該視窗所屬的程式名稱(例如 notepad.exe),在 Windows API 中需要透過以下三個步驟:- 使用
GetWindowThreadProcessId透過HWND取得該視窗的行程識別碼(Process ID, PID)。 - 使用
OpenProcess透過 PID 開啟該行程並取得權限控制代碼(hProcess)。 - 使用
GetModuleFileNameEx取得該行程的完整執行檔路徑,再從中切出檔名。 [1, 2]
由於 VC6(Visual C++ 6.0)非常古老,直接使用
psapi.h 容易遇到 SDK 版本不相容或缺少 psapi.lib 的連結錯誤。為了確保完全不依賴專案設定、不需要手動加入內含庫(Library),最安全且相容性最高的方法是使用 LoadLibrary 動態載入 psapi.dll。 [3, 4] C 語言原始碼
請將以下程式碼直接覆蓋到您 VC6 的
.c 檔案中:程式執行效果範例
執行後,您的 Console 視窗會呈現類似以下的精準對應表:
為什麼這段程式可以在 VC6 完美執行?
傳統在 VC6 呼叫
GetModuleFileNameEx 時,必須在專案設定的 Link 頁面手動輸入 psapi.lib,否則編譯會噴出 LNK2001: unresolved external symbol 的錯誤。本程式採用 Runtime 動態載入(LoadLibrary + GetProcAddress),徹底繞過了這個老舊編譯器的痛點,不需要修改任何 VC6 的專案設定即可直接編譯通過。 [3] 現在您已經能同時掌握「視窗標題」與「程式名稱(如
notepad.exe)」了,請問:- 您是否需要將這個邏輯結合,改成「只要發現
chrome.exe開啟,就自動把它移到特定位置」的自動化工具? - 還是您有遇到特定視窗(例如多螢幕環境下)名稱抓不到的問題?
沒有留言:
張貼留言