keyhac で画面3分割


Windows には、 Win キーと矢印キーの同時押しで画面を左右2分割（上下も含めると4分割）できる「スナップ機能」があります。今回は [keyhac](https://sites.google.com/site/craftware/keyhac-ja) でこの機能を拡張し、1:2 の比率でもスナップできるようにしてみます。

ウィンドウを並べて閲覧したいけれど半分だと小さすぎるし、かといって手で都度リサイズするのも煩わしい……などとお悩みの方にオススメです。

（完成イメージ↓）
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/2d7a3e27-7774-0e77-a39e-513a76e6ecbc.png)

## コード

`config.py` の関数 `configure` の中身を書いていきます。
　※今回は最低限の部分のみ記述しています。基本的な設定等は [以前の記事](https://qiita.com/AWtnb/items/5eafc1ef6846f39fca76) 参照。

```python
def configure(keymap):

    keymap.replaceKey("(28)", 236)      # 変換キーに仮想コード236を割り当て
    keymap.defineModifier(236, "User1") # 変換キーを仮想修飾キー "U1" として使う

    def triple_snap(position = "center", Narrow = False):
        main_monitor_info = (pyauto.Window.getMonitorInfo())[0]
        non_taskbar_area = main_monitor_info[1]
        [monitor_left, monitor_top, monitor_right,monitor_bottom] = non_taskbar_area
        monitor_width = monitor_right - monitor_left
        ratio = 3
        if Narrow:
            wnd_width = int(monitor_width / ratio)
            wnd_pos_table = {
                "center": {
                    "left": wnd_width,
                    "right": wnd_width * 2,
                },
                "left": {
                    "left": monitor_left,
                    "right": wnd_width,
                },
                "right": {
                    "left": wnd_width * 2,
                    "right": monitor_right,
                },
            }
        else:
            wnd_width = int(monitor_width / ratio) * 2
            wnd_pos_table = {
                "center": {
                    "left": int(monitor_width / ratio / 2),
                    "right": int(monitor_width / ratio / 2) + wnd_width,
                },
                "left": {
                    "left": monitor_left,
                    "right": wnd_width,
                },
                "right": {
                    "left": int(monitor_width / ratio),
                    "right": monitor_right,
                },
            }
        wnd_area = wnd_pos_table[position]
        rect = [wnd_area["left"], monitor_top, wnd_area["right"], monitor_bottom]
        wnd = keymap.getTopLevelWindow()
        if list(wnd.getRect()) == rect:
            wnd.maximize()
        else:
            if wnd.isMaximized():
                wnd.restore()
            wnd.setRect(rect)

    for k in [
        ("U1-M"  , lambda: triple_snap("center", False)),
        ("S-U1-H", lambda: triple_snap("left"  , False)),
        ("S-U1-L", lambda: triple_snap("right" , False)),
        ("C-U1-H", lambda: triple_snap("left"  , True)),
        ("C-U1-L", lambda: triple_snap("right" , True)),
        ("C-U1-M", lambda: triple_snap("center", True)),
        ("U1-H"  , "Win-Left"),
        ("U1-L"  , "Win-Right"),
    ]:
        keymap_global[k[0]] = k[1]

```

## 実行イメージ

変換キーと M で画面中央部にモニタ幅の 2/3 でウィンドウを持ってきます。もう一度同じキーを押すと最大化します。

![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/113b7bb5-1946-dbdf-10d7-e537333b34f7.png)


同時に Ctrl を押していると幅が 1/3 に。
![fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/4f017c19-32ec-d2a3-a404-d1e6939dbf04.png)


変換キーと H・L には通常の左右スナップを割り当てて、 Shift を押していると 2/3 、 Ctrl を押していると 1/3 幅でスナップします。

---

（そもそもマルチモニタにできれば万事解決なんですけどね）