[AutoHotKey]ウィンドウをドラッグして画面からはみ出したら端寄せする


- [\[AutoHotKey\]ウィンドウを近い方に端寄せする関数（はみ出しも対応） \- Qiita](https://qiita.com/catfist/items/8fabe7975a7e68e70615)

↑の続編的な。

**まだ開発中。**

## 動機
- [MagnetWindow](https://www.vector.co.jp/soft/winnt/util/se175660.html)を使っていたが、Chromeに対して機能しなかった
- ウィンドウ同士は適当に重ねる派なので、とりあえず画面端にだけピタっとしてくれ

## 実装
### ドラッグ移動の判定
とりあえず、単純にマウス左ボタンを長押しした場合とする。
本当はウィンドウ移動の有無も判定したほうがいいけど。

```txt:SnapWindow.ahk
; ウィンドウドラッグ時にはみ出していたら端寄せ
~LButton::Return ; A_TimeSincePriorHotkeyを取るためだけ
LButton up::
    ; 修飾キー付きを排除
    ; クリックを排除
    If (A_PriorHotKey = "~LButton" and A_TimeSincePriorHotkey > 300)
    {
        SnapWindow()
    }
    Return

; ウィンドウがはみ出していたら端寄せする関数
; 現状、タスクバーが下にある場合のみ対応
SnapWindow()
{
    WinGetPos, , , , tbHeight, ahk_class Shell_TrayWnd ; タスクバーの高さ取得
    WinGetPos, VarX, VarY, AW, AH, A
    If (VarY < 0)
        DestY = 0
    Else If (VarY > (A_ScreenHeight - tbHeight - AH))
        DestY := A_ScreenHeight - AH - tbHeight + 2 ; ちょい浮くので 2 下に調整
    If (VarX < 0)
        DestX = 0
    Else If ((VarX + AW) > A_ScreenWidth)
        DestX := (A_ScreenWidth - AW)
    WinMove, A, , %DestX%, %DestY%
}
```

ドラッグ移動で発動ということは、離したタイミングで発動なので、Upホットキーということになる。

長押し判定は、`A_TimeSincePriorHotkey`がnミリ秒以上という形で行うことができる。

`A_TimeSincePriorHotkey`は、`A_PriorHotkey`（直近で発動したホットキー、ホットキーラベル内では「今回のそれ自体」は除く）からの経過時間が格納される組み込み変数。
左ボタンのUpホットキーなので、`A_PriorHotkey`が左ボタンの押下であり、かつ`A_TimeSincePriorHotkey`がある程度長ければ、左ボタンの長押しだと判断できる。
（厳密には、その間にカーソルが一定以上の距離を移動しているかも評価したほうがよいが、とりあえず省く）

ここで困るのが、`A_PriorKey`（直近で入力されたキー）からの経過時間が格納される組み込み変数はないということ。
つまり、左ボタン押下がホットキーとしてスクリプトに登録されていなければ、ホールド時間の取りようがないということになる。

よって、`~LButton::Return`が必要になるというわけ。
別に`*LButton::Send, {Blind}{LButton}`とかでもいいっちゃいいのだが、チルダで入力を通す場合、他の`LButton`を使うホットキーラベルと共存できるのがメリットとなる。

<!-- ## Chromeでカーソルが上端に張り付いた状態で離すとリサイズされる

試してダメだった
- `MouseClickDrag`、`MouseMove`を挟む

- [ホットキー \- AutoHotkey Wiki](http://ahkwiki.net/Hotkeys#Up.E3.83.9B.E3.83.83.E3.83.88.E3.82.AD.E3.83.BC)
> 押し上げイベントは、 ~ の有無にかかわらず、乗っ取られずにシステムに通知される。
> たとえば、 LShift Up::Return のようにしても、LShiftキーを離せなくすることはできない。


```txt:sample.ahk
#SingleInstance, force
; SetTitleMatchMode, RegEx
SetTitleMatchMode, 2

Esc::ExitApp,
; #if WinActive(".+ - Google Chrome$ ahk_class Chrome_WidgetWin_1 ahk_exe Chrome.exe")
#if WinActive(" - Google Chrome ahk_class Chrome_WidgetWin_1 ahk_exe Chrome.exe")
; #if WinActive("ahk_exe Chrome.exe")

; Chromeタイトルバーの高さ 44
; タブが判別できないなー
F12:: ; 通常プレイ用サイズ
    WinMove, A, , , 0, 577, 1052
    return

; RButton::
; LButton::
;     Send, {LButton}
;     Return

~LButton up::
    WinGetPos, wX, wY, wWidth, wHeight, A
    Sleep, 200
    ; WinMove, A, , , 0,
    WinMove, A, , wX, 0, , wHeight
    Return

; ~LButton up::
;     CoordMode, Mouse, Relative
;     MouseGetPos, OutputVarX, OutputVarY,
;     CoordMode, Mouse, Screen
;     MouseGetPos, OutputVarX2, OutputVarY2,
;     If (OutputVarY2 = 0)
;     {
;         MouseClickDrag, L, 0, 0, 0, 10, R
;         ; MouseMove, 0, 50, 0, R
;     }
;     if (OutputVarY < 45)
;     {
;         ; CoordMode, Mouse, Relative
;         WinMove, A, , , 0,
;         ; MsgBox, , %A_scriptname%, Ok
;         ; Send, {LButton}
;     }
;     Return
;     ; 最悪ウィンドウ座標を記録して復元
```

結局、Chromeで上はみ出しのときだけ`Sleep`入れてから高さ込みで`WinMove`

```txt:sample.ahk
SnapWindow()
{
    WinGetPos, , , , tbHeight, ahk_class Shell_TrayWnd ; タスクバーの高さ取得
    WinGetPos, VarX, VarY, AW, AH, A
    If (VarY < 0)
        {
            ; WinMove, A, , , 0,
            ; Chromeで上端ギリで離したときリサイズされる問題の対策
            if WinActive("ahk_class Chrome_WidgetWin_1 ahk_exe Chrome.exe")
                Sleep, 500
            WinMove, A, , , 0, , AH
        }
    Else If (VarY > (A_ScreenHeight - tbHeight - AH))
        WinMove, A, , , (A_ScreenHeight - AH - tbHeight + 2) ; ちょいタスクバーから浮くので+2
    If (VarX < 0)
        WinMove, A, , 0, ,
    Else If ((VarX + AW) > A_ScreenWidth)
        WinMove, A, , (A_ScreenWidth - AW)
}
``` -->