[AutoHotKey]FileSelectFileのクソ野郎を置き換える関数


## 動機
- [FileSelectFileはクソ野郎だ](https://qiita.com/catfist/items/a50aec57d31b2ebb3547)
- 引数としてファイルパスを受け取るスクリプトで、引数がなかったときにファイル選択……とかやろうとすると、処理が複雑になってしまう
- ファイルを選択して、ファイルパスのリストに直す関数を書こう

## FileSelectFileの出力をフルパスに直す
基本的には前やったアレ

- [\[AutoHotKey\]FileSelectFileの複数選択がクソなのでなんとかする \- Qiita](https://qiita.com/catfist/items/a50aec57d31b2ebb3547)

関数内で`FileSelectFile`して出力をなんとかする

## 関数から複数のファイルパスを取り出す方法
基本的に、上に書いたものほどスマートだと思う。

### 配列
配列を関数の戻り値とすることで、`For index`でのループ処理ができる。

```txt:sample.ahk
; 変数に格納してもおｋ
; Array2 := FileSelect(Public . "\Pictures")
; For index, element in Array2

; 配列に格納されたファイルパスを表示する
For index, element in FileSelect(Public . "\Pictures")
{
    MsgBox % "Element number " . index . " is " . element
}
Return

FileSelect(Dir="",PromptTitle="",ExtFilter=""){
    Array := Object() ; 配列オブジェクトを作成

    ; ファイルの選択
    FileSelectFile, OutputVar , M, %Dir%, %PromptTitle%, %ExtFilter%

    If ErrorLevel = 1 ; ファイルを選択せずダイアログを閉じた場合
    {
        MsgBox, , %A_scriptname%, ファイルが選択されていません
        Exit
    }

    Loop, Parse, OutputVar ,`n
    {
        if A_Index = 1
        {
            SelectedDir = %A_LoopField%
        }
        Else If not A_LoopField = ""
        {
            Array.Insert(SelectedDir . "\" . A_LoopField)
        }
    }
    Return, Array ; 配列を戻り値とする
}
```

### ByRefパラメータによる変数参照
ByRefパラメータを設定することで、パラメータとして指定した変数名の変数に、関数内で格納した内容を参照することができる。
適当なデリミタ（下記コードでは改行）区切りでひとつの変数に格納すれば、`Loop, Parse`でループ処理ができる。

また、普通に`Return`すれば、戻り値としても得ることができる。

```txt:sample.ahk
ResultVar2 := FileSelect(ResultVar, Public . "\Pictures\Capture")
MsgBox, , %A_scriptname%,
(
ResultVar = %ResultVar%
ResultVar2 = %ResultVar2%
)
Return

FileSelect(ByRef OutputVar,Dir="",PromptTitle="",ExtFilter=""){
    FileSelectFile, SelectedFiles , M, %Dir%, %PromptTitle%, %ExtFilter%
    If ErrorLevel = 1 ; ファイルを選択せずダイアログを閉じた場合
    {
        MsgBox, , %A_scriptname%, ファイルが選択されていません
        Exit
    }

    Loop, Parse, SelectedFiles ,`n
    {
        if A_Index = 1
        {
            SelectedDir := A_LoopField
        }
        Else If not A_LoopField = ""
        {
            OutputVar := OutputVar . SelectedDir . "\" . A_LoopField . "`n"
        }
    }
    StringTrimRight, OutputVar, OutputVar, 1 ; 最後の改行を削除
    Return, OutputVar ; ついでに戻り値としても出力する
}
```

### グローバル変数
これはちとややこしい。

関数のパラメータとして変数名を与えれば、関数内で可変変数として内容を格納することができる。
さらに、グローバル変数として宣言することで、その内容を関数外からも参照できる。
やはり`Loop, Parse`での処理になる。

宣言は関数外で行ってもよいが、関数内で宣言したほうが手間がない。
ただし、`global %OutputVar%`のように、可変変数を宣言することはできない。
関数の最初の行に`global`とだけ記述すれば、関数内で宣言された変数は全てグローバル変数になるので、今回はこの方法を取る。
この場合、`%OutputVar%`と宣言される変数、つまり、`OutputVar`パラメータの内容を変数名とする変数が該当する。下記のコードでいえば、変数`ResultVar`のこと。

ただし、色々試したが、`Return`で返すことはできなかった。

```txt:sample.ahk
FileSelect("ResultVar", "", "hoge", "画像ファイル(*.jpg;*.png;*gif)")
MsgBox, , %A_scriptname%, ResultVar = %ResultVar%

Return


FileSelect(OutputVar,Dir,PromptTitle,ExtFilter){
    global
    local SelectedDir ; 関数内で定義される変数なので、外部参照されないようlocal宣言する

    FileSelectFile, SelectedFiles , M, %Dir%, %PromptTitle%, %ExtFilter%

    If ErrorLevel = 1 ; ファイルを選択せずダイアログを閉じた場合
    {
        MsgBox, , %A_scriptname%, ファイルが選択されていません
        Exit
    }

    Loop, Parse, SelectedFiles ,`n
    {
        if A_Index = 1
        {
            SelectedDir := A_LoopField
        }
        Else If not A_LoopField = ""
        {
            %OutputVar% := %OutputVar% . SelectedDir . "\" . A_LoopField . "`n"
        }
    }
    StringTrimRight, %OutputVar%, %OutputVar%, 1 ; 最後の改行を削除
    ; Return, %OutputVar% ; なんかできない
}
```