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

PowerShell 7 - ウィンドウのサイズを変えるスクリプト 座標データ取得と設定

【連載】

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

【第160回】PowerShell 7 - ウィンドウのサイズを変えるスクリプト 座標データ取得と設定

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

前回はPowerShellからWindows APIを使用する方法を紹介した。基本的な部分のみを取り上げたが、それだけでも結構いろいろとできるようになったはずだ。今回はこの機能を使って、アプリケーションの座標データを取得し、さらにその座標データを変更して表示場所やサイズを変更する方法を紹介する。

必要になるWindows APIを絞り込む

今回は次のスクリプトを参考にして説明を行っている。


上記スクリプトでは、user32.dllを読み込んで、次の3つの関数を利用している。

  • GetWindowRect()
  • GetClientRect()
  • MoveWindow()


GetWindowRect()とGetClientRect()は似たような動作をする。アプリケーションウインドウの座標データ(左上X座標、左上Y座標、右下X座標、右下Y座標)を得るための関数だ。しかし、対象が異なっている。GetWindowRect()はタイトルバーといった装飾も含めたウインドウの座標データ、GetClientRect()はタイトルバーといった装飾を抜いた中身だけの座標データだ。

ここではウインドウのタイトルバーも含めてサイズを変更できればよいので、GetWindowRect()を使えばよい。MoveWindow()はウィンドウを指定した座標(左上X座標、左上Y座標、幅、高さ)に設定する関数だ。つまり、次の2つの関数を使えばよいことになる。


この2つの関数のシンタックスは、上記マニュアルによればそれぞれ次の通りだ。

GetWindowRect function (winuser.h)

BOOL GetWindowRect(
  HWND   hWnd,
  LPRECT lpRect
);

MoveWindow function (winuser.h)

BOOL MoveWindow(
  HWND hWnd,
  int  X,
  int  Y,
  int  nWidth,
  int  nHeight,
  BOOL bRepaint
);

前回の方法に倣って、この2つの関数を使えるようにしてみよう。

PowerShellから使えるように「Add-Type」で整える

先ほどの2つの関数をPowerShellから扱えるようにAdd-Typeコマンドレットで整理すると次のようになる。

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);
}
"@

前回との違いは、Add-Typeコマンドレットの中で「RECT」という構造体を定義していることだ。GetWindowRect()関数が「RECT」という構造体を使うので、これを上記のように書いておく必要がある。詳しい説明は省くが、現時点では、こうやって書くものだと思っておいてもらえればと思う。

用意したWindows APIを使用する

Add-Typeコマンドレットで整理した関数は、次のように使うことになる。

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

# ウインドウの現在の座標データを取得
[WinAPI]::GetWindowRect(ウインドウハンドラ, [ref]$rc)

# 左上の場所はそのままに、ウインドウのサイズを変更
[WinAPI]::MoveWindow(ウインドウハンドラ, $rc.Left, $rc.Top, 幅, 高さ, $true)

ウインドウの左上の位置は変えることなく縦と横のサイズを調整したい。これはウインドウの右下をマウスやタッチパッドで掴んでウインドウサイズを変更する操作と同じだ。このため、対象となるアプリケーションの座標データを最初に得て、左上の座標を知る必要があるのだ。

まず、座標データを格納する構造体をオブジェクトとして生成する。次に、[WinAPI]::GetWindowRect関数を呼び出す。この処理でRECTのオブジェクトである$rcに座標データが格納される。次に[WinAPI]::MoveWindow関数で、先ほど取得した左上の座標データと、目的とする幅と高さを指定すれば、対象とするアプリケーションのサイズが良い具合に変更されるというわけだ。

window_resizer.ps1 ver.2

今回の内容をPowerShellスクリプトにまとめてみよう。動作が確認できればよいので、対象とするアプリケーションやウインドウサイズはスクリプトに直接書いておく。対象となるアプリケーションのプロセスを特定する方法は、前々回にまとめた内容をそのまま使う。整理すると次のようになる。

window_resizer.ps1

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);
}
"@

$processName="msedge"
$windowTitle=".*"
$width="1200"
$height="1200"

Get-Process -Name $processName |
        ? { $_.MainWindowHandle -ne 0 } |
        ? { $_.MainWindowTitle -match "$windowTitle" } |
        % {
                # ウインドウ座標データ構造体
                $rc = New-Object RECT

                # ウインドウの現在の座標データを取得
                [WinAPI]::GetWindowRect($_.MainWindowHandle, [ref]$rc)

                # 左上の場所はそのままに、ウインドウのサイズを変更
                [WinAPI]::MoveWindow($_.MainWindowHandle, $rc.Left, $rc.Top, $width, $height, $true)
}

スクリプトに直接書いたサイズを書き変えながらスクリプトを実行してみると、次の結果が得られる。

Microsoft Edge 1200x1200

Microsoft Edge 1200x1000

Microsoft Edge 1200x800

Microsoft Edge 1200x600

かなり想定した挙動に近づいてきた感じだ。

PowerShellスクリプトで生産効率を引き上げよう

アプリケーションのウインドウサイズを変更するスクリプトの本質となる処理は、今回のスクリプトがほぼ押さえている。さらに何かやるとすれば、このスクリプトをもう少し汎用的に扱えるように整えたり、ちょっと機能拡張を行ったりするくらいだ。

整えたPowerShellスクリプトは、環境変数PATHの通ったフォルダに置いておけば、コマンドやコマンドレットのように扱うことができる。ほかのスクリプトやバッチファイルから呼び出すことも可能だ。こうした”ちょっと便利なスクリプト”を積み上げていくことで、これまで手動で行っていた操作を少しずつだが自動化していくことができるのだ。一つ一つで得られる時短効果はごくわずかかもしれないが、これが積み重なると結構大きな違いになってくる。コツコツ便利なスクリプトを作成して、操作効率を引き上げていこう。

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

一覧はこちら

連載目次

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

【連載】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用語の意味を事典でチェック!

一覧はこちら

会員登録(無料)

ページの先頭に戻る