(PowerShell) 5分待て。俺がGUIのモックを書いてやる、ビルドフォーーーム！！


脳内では水木兄ぃの歌声が聞こえてきそうです。
それはさておき、PowerShellでGUIのモックアップが簡単にできるツールを作りました。

Formをグリッドに見立ててDSLなCSVでコントロールを配置します。
動くスクリプトをすばやく手軽に生成可能です。
慣れたら5分でコントロールを10個くらい配置できる（！）と思います。


## サンプル
こんなCSVを書くと
![buildForm_CSV.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284224/60da2ccb-a2b9-c81e-33dd-0d5edbb1ee4d.png)

生成される画面はこんな感じです。
![buildForm_Sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284224/3996ebe5-1dc0-f1bf-bbd3-7d105972981f.png)
6行のCSVから92行(空行込み)のスクリプトが生成されました。


## 記法
+ **コントロール_名前** 
スクリプト上で$buttonOKとするなら、button_OKとします。

+ **コントロール\_名前\_キャプション**
コントロール上に名前とは違う文字を表示したい場合、アンダースコアに続けてキャプションを記載します。button_Cancel_取消 等。
ListViewに限りキャプションを|で区切って項目を列挙できます。

+ **コントロール:横倍率/縦倍率_名前** 
コントロールのサイズは一律ですが、整数倍でサイズ指定も可能です。横方向にだけ伸ばしたい場合、textBox:2/1_Name 等。さらに右にコントロールを配置するなら空項目(カンマのみ)の挿入を忘れずに！

+ **省略型** 
よく使うコントロールには省略型も用意しました。B_OKでも大丈夫。（サンプルはこればっかり。）

|省略型|コントロール|
|----|----|
|B|button|
|L|label|
|M|comboBox|
|R|radioButton|
|T|textBox|
|V|listView|
|X|checkBox|


## 使い方
+ CSVを前述の記法で作成します。(BOM付UTF-8 括り文字なし)
+ PowerShellやVS Codeのコンソール等で生成します。

````powershell
>./buildForm.ps1 form.csv | out-file -encoding:utf8 form.ps1
````

+ 生成したスクリプトを実行  
 
````powershell
>./form.ps1
````

## スクリプト本体
````powershell:buildForm.ps1


# コントロールサイズ
$cWidth = 70
$cHeight = 25

# コントロール間のマージン
$xMar = 5
$yMar = 5

# 画面サイズ
$formWidth = 0
$formHeight = 0

# 画面のマージン
$formMarx = 15
$formMary = 15

# コントロール配置座標
$xPos = $xMar + $formMarx
$yPos = $yMar + $formMary

$tmpArr = $Args[0].split(".")
$winTitle = $tmpArr[0]

#windowsフォーム
Write-Output ("Add-Type -AssemblyName System.Windows.Forms")
Write-Output ("Add-Type -AssemblyName System.Drawing")
Write-Output ("")

#フォームの作成"
Write-Output ("`$form      = New-Object System.Windows.Forms.Form")
Write-Output ("`$form.Text = `"$winTitle`"")
Write-Output ("")

$row = 0
foreach($line in (Get-Content $Args[0])){

    # CSVをカンマで分割
    $ctrls = $line.split(",")

    $xPos = $xMar + $formMarx

    foreach($ctrl in $ctrls){
        if ($ctrl -ne ""){

            # 項目をアンダースコアで分割
            $ctrlInfo = $ctrl.Split("_")

            # コントロールサイズ指定の反映 
            $setWidth  = $cWidth
            $setHeight = $cHeight

            # ex) T:2/1   テキストボックスのサイズをX方向に2倍、Y方向に1倍
            $tmpArr   = $ctrlInfo[0].Split(":")
            $ctrlCode = $tmpArr[0]

            if ($tmpArr.Length -eq 1){
            } else {
            # コントロールサイズ倍率の反映 
            if ($tmpArr[1].contains("/")){
                    $sizeArr   = $tmpArr[1].Split("/")
                    $setWidth  = [int]$sizeArr[0] * ($cWidth  + $xMar) - $xMar
                    $setHeight = [int]$sizeArr[1] * ($cHeight + $yMar) - $yMar
                }
            }

            # コントロールタイプの設定
            # 一致しなければ指定されたタイプをそのまま使用
            switch ($ctrlCode) {
                "L"{$ctrlType="label"}
                "T"{$ctrlType="textBox"}
                "B"{$ctrlType="button"}
                "R"{$ctrlType="radioButton"}
                "X"{$ctrlType="checkBox"}
                "M"{$ctrlType="comboBox"}
                "V"{$ctrlType="listView"}
                Default {$ctrlType=$ctrlCode}
            }

            # コントロール名の設定
            $ctrlName=$ctrlInfo[1]

            # コントロールのキャプション(Textプロパティ)の設定
            # 指定がなければコントロール名をコピー
            # ex) L_OK_了解  :了解
            #     L_OK       :OK

            if ($ctrlInfo.Length -eq 2){
                $ctrlCaption = $ctrlName
            }else{
                $ctrlCaption = $ctrlInfo[2]
            }
            $ctrlID = $ctrlType + $ctrlName

            # コントロール生成
            Write-Output ("`${0}           = New-Object System.Windows.Forms.{1}"      -f $ctrlID,$ctrlType)
            Write-Output ("`${0}.Location  = New-Object System.Drawing.Point({1},{2})" -f $ctrlID, $xPos, $yPos)
            Write-Output ("`${0}.Size      = New-Object System.Drawing.Size({1},{2})"  -f $ctrlID, $setWidth, $setHeight)
    
            # コントロール個別の処理
            switch -Regex ($ctrlType){
                "label|button|radioButton|checkBox"{
                    Write-Output ("`${0}.Text      = `"{1}`"" -f $ctrlID, $ctrlCaption)
                    if ($ctrlType -eq "label"){
                        Write-Output ("`${0}.TextAlign = `"MiddleLeft`"" -f $ctrlID)
                    }
                }
                "listView"{
                    Write-Output ("`${0}.View      = `"Details`"" -f $ctrlID)

                    # キャプションを|で区切り、列名として追加
                    foreach($li in ($ctrlCaption.split("|"))){
                        Write-Output ("`${0}.Columns.Add(`"{1}`",{2})" -f $ctrlID, $li,$cWidth)
                    }
                }
                "textBox"{
                    if ($setHeight -gt $cHeight){
                        Write-Output ("`${0}.Multiline = `$True" -f $ctrlID)
                    }
                }
            }
    
            # コントロールを画面に追加
            Write-Output ("`$Form.controls.Add(`${0})" -f $ctrlID)
            Write-Output ("")
        }

        # コントロールX座標移動
        $xPos = $xPos + $setWidth + $xMar
    }

    #フォーム幅設定
    $xPos = $xPos + $xMar + $formMarx
    if ($xPos -gt $formWidth){
        $formWidth = $xPos
    }

    # コントロールY座標移動
    $yPos = $yPos + $setHeight + $yMar

    $row = $row + 1
} 

#フォーム高さ設定
$yPos = $yPos + $cHeight + $yMar + $formMary
$formHeight = $yPos

Write-Output ("`$form.Size = New-Object System.Drawing.Size({0},{1})" -f $formWidth,$formHeight)
Write-Output ("`$result    = `$form.ShowDialog()")

````

これでEXCELのない環境でもGUIのツールが使える、みたいな。

2020/6/8 textBoxの高さ変更についてMultiline=$Trueを追加しました。