マイナビニュースマイナビ

ウインドウを配置するスクリプト  - window_deploy.ps1

【連載】

PowerShell Core入門 - 基本コマンドの使い方

【第167回】ウインドウを配置するスクリプト - window_deploy.ps1

[2021/09/24 08:00]後藤大地 ブックマーク ブックマーク

これまでにウインドウのサイズを変更するスクリプトと、ウインドウを移動させるスクリプトを作ってきた。この2つのスクリプトを組み合わせると、ウインドウを任意の場所に任意のサイズで配置することが可能になる。

ウインドウを任意の位置に任意のサイズで配置することができるようになると、デスクトップのアプリケーション配置を自動的に行うことが可能になる。仕事などで日々作業していると、ある程度アプリケーションウインドウの配置が決まってくるものだ。ここにはこのアプリケーション、こっちにこのアプリケーションを置いておくといった具体だ。今回は、スクリプトでその配置処理を自動化しよう。

Windowsは左右や上下への配置に関してはウインドウを貼り付けておくことができるが、それ以外の配置はそれほど得意ではない。より細かい配置をPowerShellスクリプトを使って行うことで、「いつものデスクトップ」を素早く整えてしまおう。

window_deploy.ps1

ではさっそく結果となる「window_deploy.ps1」から見てみよう。

#!/usr/bin/env pwsh

#====================================================================
# 引数を処理
#====================================================================
Param(
    [String]$ProcessName="*",   # プロセス名
    [String]$WindowTitle=".*",  # ウィンドウタイトル(正規表現)
    [Int32]$X="0",              # ウィンドウ左上X座標
    [Int32]$Y="0",              # ウィンドウ左上Y座標
    [Int32]$Width="0",          # ウィンドウ幅
    [Int32]$Height="0",         # ウィンドウ高さ
    [Switch]$WindowProcessList  # ウィンドウプロセス一覧を表示
)

#====================================================================
# ウィンドウプロセスを一覧表示
#====================================================================
if ($WindowProcessList) {
    Get-Process                         | 
    ? {$_.MainWindowHandle -ne 0 }              | 
    Format-Table -Property Id,ProcessName,MainWindowTitle
    exit
}

#====================================================================
# Win32 APIのインポート
#====================================================================
Add-Type @"
using System;
using System.Runtime.InteropServices;

public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

public class WinAPI
{
    // ウィンドウの現在の座標データを取得する関数
    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

    // ウィンドウの座標を変更する関数
    [DllImport("user32.dll")]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); 

    // スクリーンサイズを取得する関数
    [DllImport("user32.dll")]
    public static extern int GetSystemMetrics(int nIndex); 
}
"@

#====================================================================
# ウィンドウを配置する関数 Move-Deploy
#====================================================================
function Deploy-Window {
    param (
        $wh  # ウィンドウハンドラ
    )

    # ウィンドウ座標データ構造体
    $rc = New-Object RECT

    # ウィンドウの現在の座標データを取得
    [WinAPI]::GetWindowRect($wh, [ref]$rc) > $null

    # 幅の指定がない場合、取得した座標データからウィンドウの幅を計算
    if ($Width -eq 0) {
        $Width = $rc.Right - $rc.Left;
    }

    # 高さの指定がない場合、取得した座標データからウィンドウの高さを計算
    if ($Height -eq 0) {
        $Height = $rc.Bottom - $rc.Top;
    }

    # マイナス指定のXおよびYを正値へ変換
    if ($X -lt 0) {
        # スクリーン幅を取得
        $screenWidth = [WinAPI]::GetSystemMetrics(0);
        # Xの値を算出
        $X = $screenWidth + $X - $Width
    }
    if ($Y -lt 0) {
        # スクリーン高さを取得
        $screenHeight = [WinAPI]::GetSystemMetrics(1);
        # Yの値を算出
        $Y = $screenHeight + $Y - $Height
    }

    # ウィンドウを指定された座標に指定されたサイズで配置する
    [WinAPI]::MoveWindow($wh, $X, $Y, $Width, $Height, $true) > $null
}

#====================================================================
# 対象となるウィンドウを選択し、サイズを変更
#====================================================================
Get-Process -Name $processName |
    ? { $_.MainWindowHandle -ne 0 } |
    ? { $_.MainWindowTitle -match "$windowTitle" } |
    % {
        # ウィンドウを配置
        Deploy-Window($_.MainWindowHandle);
}

ベースとしては前回仕上げたwindow_move.ps1からの書き換えがわかりやすい。どのように書き換えを行ったかwindow_move.ps1との変更分を次に掲載しておく。

--- window_move.ps1 2021-09-16 19:44:04.892607000 +0900
+++ window_deploy.ps1   2021-09-16 19:44:07.860428000 +0900
@@ -6,8 +6,10 @@
 Param(
    [String]$ProcessName="*",   # プロセス名
    [String]$WindowTitle=".*",  # ウィンドウタイトル(正規表現)
-   [Int32]$X="0",              # ウィンドウ幅
-   [Int32]$Y="0",              # ウィンドウ高さ
+   [Int32]$X="0",              # ウィンドウ左上X座標
+   [Int32]$Y="0",              # ウィンドウ左上Y座標
+   [Int32]$Width="0",          # ウィンドウ幅
+   [Int32]$Height="0",         # ウィンドウ高さ
    [Switch]$WindowProcessList  # ウィンドウプロセス一覧を表示
 )

@@ -53,9 +55,9 @@
 "@

 #====================================================================
-# ウィンドウを移動する関数 Move-Window
+# ウィンドウを配置する関数 Move-Deploy
 #====================================================================
-function Move-Window {
+function Deploy-Window {
    param (
        $wh  # ウィンドウハンドラ
    )
@@ -66,26 +68,32 @@
    # ウィンドウの現在の座標データを取得
    [WinAPI]::GetWindowRect($wh, [ref]$rc) > $null

-   # 取得した座標データからウィンドウの幅と高さを計算
-   $width = $rc.Right - $rc.Left;
-   $height = $rc.Bottom - $rc.Top;
+   # 幅の指定がない場合、取得した座標データからウィンドウの幅を計算
+   if ($Width -eq 0) {
+       $Width = $rc.Right - $rc.Left;
+   }

+   # 高さの指定がない場合、取得した座標データからウィンドウの高さを計算
+   if ($Height -eq 0) {
+       $Height = $rc.Bottom - $rc.Top;
+   }
+
    # マイナス指定のXおよびYを正値へ変換
    if ($X -lt 0) {
        # スクリーン幅を取得
        $screenWidth = [WinAPI]::GetSystemMetrics(0);
        # Xの値を算出
-       $X = $screenWidth + $X - $width
+       $X = $screenWidth + $X - $Width
    }
    if ($Y -lt 0) {
        # スクリーン高さを取得
        $screenHeight = [WinAPI]::GetSystemMetrics(1);
        # Yの値を算出
-       $Y = $screenHeight + $Y - $height
+       $Y = $screenHeight + $Y - $Height
    }

-   # ウィンドウのサイズはそのままに、左上の場所を変更
-   [WinAPI]::MoveWindow($wh, $X, $Y, $width, $height, $true) > $null
+   # ウィンドウを指定された座標に指定されたサイズで配置する
+   [WinAPI]::MoveWindow($wh, $X, $Y, $Width, $Height, $true) > $null
 }

 #====================================================================
@@ -95,6 +103,6 @@
    ? { $_.MainWindowHandle -ne 0 } |
    ? { $_.MainWindowTitle -match "$windowTitle" } |
    % {
-       # ウィンドウを移動
-       Move-Window($_.MainWindowHandle);
+       # ウィンドウを配置
+       Deploy-Window($_.MainWindowHandle);
 }

次にそれぞれの変更分を見ていこう。

パラメータに幅と高さを追加

window_move.ps1はウィンドウを移動するスクリプトだ。このため、パラメータに幅と高さは含まれていない。追加するのは以下のコードだ。

Param(
    [String]$ProcessName="*",   # プロセス名
    [String]$WindowTitle=".*",  # ウィンドウタイトル(正規表現)
    [Int32]$X="0",              # ウィンドウ左上X座標
    [Int32]$Y="0",              # ウィンドウ左上Y座標
    [Int32]$Width="0",          # ウィンドウ幅
    [Int32]$Height="0",         # ウィンドウ高さ
    [Switch]$WindowProcessList  # ウィンドウプロセス一覧を表示
)

今回のスクリプトはウインドウを任意の場所に配置するためにX座標、Y座標、幅、高さを指定する。このためここで上記のように-Widthと-Heightが追加してある。

パラメータで幅と高さが指定されていない場合には、現在のウインドウの幅と高さを使いたい。この判断をするのに、幅と高さのデフォルト値として「0」を指定している。幅や高さが「0」だった場合には、現在のウインドウのサイズを指定して使うようにする。

Deploy-Window()関数

window_move.ps1ではMove-Window()関数でウインドウを移動させていた。今度は移動とサイズ指定と両方行うので、以下のように名前をDeploy-Window()へ変更する。

function Deploy-Window {

この関数で変更するのは幅の指定と高さの指定だけだ。幅や高さの値が「0」だった場合、ユーザーから幅や高さの指定が行われていないとし、次のように現在のウインドウの幅や高さを取得して設定するようにする。

    # 幅の指定がない場合、取得した座標データからウィンドウの幅を計算
    if ($Width -eq 0) {
        $Width = $rc.Right - $rc.Left;
    }

    # 高さの指定がない場合、取得した座標データからウィンドウの高さを計算
    if ($Height -eq 0) {
        $Height = $rc.Bottom - $rc.Top;
    }

Windows APIの呼び出し部分をちょっと調整してこの関数は完成だ。

    # ウィンドウを指定された座標に指定されたサイズで配置する
    [WinAPI]::MoveWindow($wh, $X, $Y, $Width, $Height, $true) > $null

Deploy-Window()関数呼び出し部分を変更

最後に、これまでMove-Window()関数を呼び出していた部分を、Deploy-Window()関数を呼び出すように変更すればスクリプトは完成だ。

+       # ウィンドウを配置
+       Deploy-Window($_.MainWindowHandle);

さっそく使ってみよう

作ったスクリプトを実行してみよう。次のように座標とサイズを指定して実行する。

window_deply -ProcessName msedge -X 100 -Y 100 -Width 1200 -Height 800

実行結果

座標もサイズも指定できる。そして座標はマイナス値も指定できるので、次のような指定方法も可能だ。

window_deploy -ProcessName msedge -X -100 -Y -100 -Width 1500 -Height 1000

実行結果

座標の指定は正値と負値を組み合わせることもできる。

window_deploy -ProcessName msedge -X 700 -Y -100 -Width 1000 -Height 1300

実行結果

こんな感じでウインドウを自由に配置できるようになると、複数のアプリケーションを同時に好きな場所に配置するといったことができるようになる。今回はその基盤となるスクリプトを作成した。次回は、具体的にどうやって配置スクリプトを作成すればよいかについて説明する。

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

もっと知りたい!こちらもオススメ

【連載】RPA入門 - ツールで学ぶ活用シーン

【連載】RPA入門 - ツールで学ぶ活用シーン

AIには、ルールベース、機械学習、深層学習(ディープラーニング)の3つのレベルがあり、レベルが上がるに連れてより高度な人工知能を実現しますが、AIのスピンオフという位置付けで、Digital Labor(仮想知的労働者)によるホワイトカラー業務の自動化を実現するRPAが注目されています。

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で TECH+ の人気記事をお届けします
注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
Slackで始める新しいオフィス様式
Google Workspaceをビジネスで活用する
ニューノーマル時代のオウンドメディア戦略
ミッションステートメント
次世代YouTubeクリエイターの成長戦略
IoTでできることを見つけるための発想トレーニング
教えてカナコさん! これならわかるAI入門
AWSではじめる機械学習 ~サービスを知り、実装を学ぶ~
Kubernetes入門
SAFeでつくる「DXに強い組織」~企業の課題を解決する13のアプローチ~
マイクロサービス時代に活きるフレームワーク Spring WebFlux入門
AWSで作るマイクロサービス
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

会員登録(無料)

ページの先頭に戻る