torazaemon2016’s blog

手書き文字認識メモ開発

AutohotkeyでGUIメニューを表示し、ペン1本で PCを操作する

Autohotkeyを使ってGUIメニューを出すことでキーボードがなくてもPCを操作する環境を作る。

Autohotkeyなのに、キーボードなしって、ちょっと意味がわからない話になっていますが、 タブレットPCでキーボード付けない軽いPC環境をを目指しているのでキーボードはないです。

せっかく軽いSurface GOに 重いキーボードを付けることなしに 使えたらと思っています。

Autohotkeyがどういうものやらとか、インストール方法などは、インターネットを検索ください。

ここでは、Autohotkeyが導入済みのSurfaceProやGOなどでペンでPCをペンのみでPCを操作する野望を達成させることを目標にしています。

Autohotkey Ver.2 での文法変更

AHKがVer2になってからGUIの書き方も少し変わったのですが、インターネットでは Ver1でのサンプルのページばかりがヒットするため、なかなかうまく書けてなく Classを作ってうまく書けるより、まずは動作するものとして作ってています。

zenn.dev では、Ver.2でのclass とnewを使った例が紹介されています。

HWRinputとの連携

以下から実際の例です。

torazaemon2016.hatenablog.jp で紹介しているHWRinputのF13ボタンを、GUIメニューの起動ボタンにする。

F13::
{
    if WinActive("ahk_class Notepad++")
    {
        ;Send("{F1}")   ; ここでSend("F13")絶対ダメ。無限ループになる。
        GUI_menu()
    }
    else if WinActive("ahk_class Vim")
    {
        Send("{ESC}")
    }
    else
    {
        GUI_menu()
    }
    return
}

GUI_menu()

GUIでボタンで、やりたいことを登録しています。

Ver1に近い形の記載で、 やりたいことができることを確認する意味もあるので、 洗練されていませんので、どんどん拡張していただければと思います。

途中 func_ での関数は また別途定義されているものですが、また別途紹介できればと思います。

基本的にラウンチャーなので、起動時にGUIを消して、コマンドを実行している形ですが、 カーソルキーの動きの際には、一度隠して、コマンドを実行し、再度GUIを出す形です。

また、タイマーで5秒間メニューを出し、何もしなければ消える形にしています。 また、最初でGUIメニューの多重起動を避ける形にしています。

GUI_menu()
{
    If WinExist("AHK Menu")
    {
        WinActivate
        return
    }
    
    MyGui := Gui(,"AHK Menu")
 
    MyGui.BackColor := "00EE99"  ; RGB color
    MyGui.SetFont("s12")  ; フォントサイズ(ポイント)を設定

    MyGui.Add("Button", " default", "Obsidian").OnEvent("Click", Obsidian_click) ; 
    MyGui.Add("Button", " x+8", "Date").OnEvent("Click", Date_click) ; 
    MyGui.Add("Button", " x+8", "Time").OnEvent("Click", Time_click) ; 
    MyGui.Add("Button", " X+8 ", "-").OnEvent("Click", Add_item_click) ; 
    MyGui.Add("Button", " X+8 ", "- [ ] ").OnEvent("Click", Add_checkitem_click) ; 

    MyGui.Add("Button", " X16 y+20", "Edit Autohotkey ").OnEvent("Click", Edit_ahk_click) ; 
    MyGui.Add("Button", " x+8", "Edit ahk GUI").OnEvent("Click", Edit_ahk_gui_click) ; 
    MyGui.Add("Button", " x+8", "Reload AHK").OnEvent("Click", Reload_ahk_click) ; 

    MyGui.Add("Button", " x16 y+20", "Google").OnEvent("Click", Chrome_click) ; 
    MyGui.Add("Button", " x+20", "Chrome URL get").OnEvent("Click", Chrome_get_click) ; 
    MyGui.Add("Button", " x+20", "Win+Shift+s").OnEvent("Click", Capture_click) ; 

    MyGui.Add("Button", " x+60 cRed", "Shutdown").OnEvent("Click", Shutdown_click) ; 

    MyGui.Add("Button", " x16 y+20", "Gmail").OnEvent("Click", Gmail_click) ; 
    MyGui.Add("Button", " x+20", "Calendar").OnEvent("Click", Gcalendar_click) ; 

    MyGui.Add("Button", " X16 y+40", "←").OnEvent("Click", Arrow_Left) ; 
    MyGui.Add("Button", " X+8 ", "↓").OnEvent("Click", Arrow_Down) ; 
    MyGui.Add("Button", " X+8 ", "↑").OnEvent("Click", Arrow_Up) ; 
    MyGui.Add("Button", " X+8 ", "→").OnEvent("Click", Arrow_Right) ; 
    MyGui.Add("Button", " X+20 ", "^{Home}").OnEvent("Click", Goto_Head) ; 
    MyGui.Add("Button", " X+8 ", "^{End}").OnEvent("Click", Goto_Tail) ; 
    
    Aaa := WinActive("A")
    if(Aaa != 0){
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
    } else {
        Title := "no active"
    }
    MyGui.Add("Text", " x16 y+20", Title)

    MyGui.OnEvent("Escape", CloseWindow) ; [ESC] キーで閉じる
    MyGui.OnEvent("Close", CloseWindow) ; X で閉じる

    SetTimer(UpdateMenu, 5000)  ;5秒後にメニューを閉じる
    MyGui.Show("x1800 y100")

;--------------------
    UpdateMenu(*)
    {
        CloseWindow()
    }
;---MyGui を閉じる関数-----
    CloseWindow(*)
    {
        SetTimer(UpdateMenu, 0)
        Sleep(100)
        MyGui.Destroy()
    }
;--------------------
    Date_click(*)
    {
        MyGui.Destroy()
        ;IME_set(0)
        now := FormatTime(, "yyyy-MM-dd")
        Sleep(100)
        Send(now)
        Send(A_Space)
    }

    Time_click(*)
    {
        MyGui.Destroy()
        ;IME_set(0)
        now := FormatTime(, "HH:mm")
        Sleep(100)
        Send(now)
        Send(A_Space)
    }

    Edit_ahk_click(*)
    {
        MyGui.Destroy()
        Run("notepad++.exe `"" A_ScriptDir "\AutoHotkey_V2.ahk`"") ;このスクリプトを編集 
    }

    Edit_ahk_gui_click(*)
    {
        MyGui.Destroy()
        Run("notepad++.exe `"" A_ScriptDir "\GUI.ahk`"") ;このスクリプトを編集 
    }

    Reload_ahk_click(*)
    {
        msg := "`"Reload Autohotkey `"" 
        ToolTip(msg)
        Sleep(500)
        ToolTip()
        Reload()    ;このスクリプトをリロードして適用
        return
    }

    Shutdown_click(*)
    {
        MyGui.Destroy()
        func_shutdown()
    }
    
    Chrome_click(*)
    {
        MyGui.Destroy()
        func_chrome_open()
    }

    Chrome_get_click(*)
    {
        MyGui.Destroy()
        func_chrome_capture()
    }

    Capture_click(*)
    {
        MyGui.Destroy()
        Send "#+s"  ; Win+Shift+s
    }

    Gmail_click(*)
    {
        MyGui.Destroy()
        browser := "C:\Program Files\Google\Chrome\Application\chrome.exe --disk-cache-dir=R:\Temp"
        Run(browser " `"https://mail.google.com/mail/u/0/#inbox`"")
    }
    
    Gcalendar_click(*)
    {
        MyGui.Destroy()
        browser := "C:\Program Files\Google\Chrome\Application\chrome.exe --disk-cache-dir=R:\Temp"
        Run(browser " `"https://calendar.google.com/calendar/u/0/r?pli=1`"")
    }
    
    
    Obsidian_Click(*)
    {
        MyGui.Destroy()
        func_obsidian()
    }

    Add_item_click(*)
    {
        MyGui.Destroy()
        Sleep(50)
        Send "- "           
    }
    Add_checkitem_click(*)
    {
        MyGui.Destroy()
        Sleep(50)
        Send "- [ ] "       
    }

;---画面リストアする(またメニューを表示する)-----
    Arrow_Left(*)
    {
        MyGui.Hide()    ; メニュー消す (アクティブがエディタ画面に)
        Sleep(50)       ; ちょっと待つ(速すぎるとアクティブが切り替わらない)
        Send "{Left}"   ; ←移動
        Sleep(50)       ; ちょっと待つ
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
        MyGui.Restore() ; Guiメニューを表示する
        SetTimer(UpdateMenu, 5000)
    }
    Arrow_Right(*)
    {   
        MyGui.Hide()
        Sleep(50)
        Send "{Right}"          ; →移動
        Sleep(50)
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
        MyGui.Restore() ; Gui を表示する
        SetTimer(UpdateMenu, 5000)
    }
    Arrow_Down(*)
    {
        MyGui.Hide()
        Sleep(50)
        Send "{Down}"           ; ↓移動
        Sleep(50)
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
        MyGui.Restore() ; Gui を表示する
        SetTimer(UpdateMenu, 5000)
    }
    Arrow_Up(*)
    {
        MyGui.Hide()
        Sleep(50)
        Send "{Up}"         ; ↑移動
        Sleep(50)
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
        MyGui.Restore() ; Gui を表示する
        SetTimer(UpdateMenu, 5000)
    }
    Goto_Head(*)
    {
        MyGui.Hide()
        Sleep(50)
        Send "^{Home}"          ; 先頭へ移動
        Sleep(100)
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
        MyGui.show() ; Gui を表示する
        SetTimer(UpdateMenu, 5000)
    }
    Goto_Tail(*)
    {
        MyGui.Hide()
        Sleep(50)
        Send "^{End}"           ; 末尾へ移動
        Sleep(100)
        Title := WinGetTitle("A")   ;アクティブ タイトル名を取得し Title へ格納
        MyGui.show() ; Gui を表示する
        SetTimer(UpdateMenu, 5000)
    }

}

他にも、スタートメニューでは、起動しにくい、よく使うアプリを登録したり、 キー操作に該当するものを、ボタンで実行できるようにしたりなど、 利用方法は無限です。

ぜひ使いやすいように、カスタマイズして、 「キーボードのないPC」でPCを使いこなしてください。