AutoHotkey 2.0でLIFOのテキストスタックシステムを実現する(VZエディタやWZエディタと同じLIFOを実現する仕組みの実現)

  • このスクリプトを意図通りに動作させるには、管理者権限で実行する必要があります。
  • AutoHotkeyのファイルをスタートメニューに置くだけでは、PC起動時に管理者権限で実行されません。
  • スタートアップフォルダにショートカットを置くだけでは、セキュリティ(UAC)の制限で管理者権限が解除されるか、エラーになってしまいます。 これを解決するための最も確実で安全な2つの方法を解説します。

方法1:Windowsの[タスクスケジューラ]を使う(★★★最も推奨)

Windowsの標準機能である[タスクスケジューラ]を使えば、PC起動時にログインしたタイミングで、UACの警告なしで管理者権限のままスクリプトを自動起動できます。

  1. キーボードのWin + Rを押し、taskschd.mscと入力してEnterを押します。
  2. 右側の操作パネルから[基本タスクの作成]をクリックします。
  3. 名前に分かりやすい名前(例:AHK_Startup)を入力し、[次へ]を進めます。
  4. トリガーで[ログオン時]を選択し、[次へ]を進めます。
  5. 操作で[プログラムの開始]を選択し、[次へ]を進めます。
  6. プログラム/スクリプトの[参照]ボタンから、実行したいAutoHotkeyスクリプト(.ahkファイルまたはコンパイルした.exeファイル)を選択します。
  7. [完了]をクリックしてタスクを一度作成します。
  8. 作成したタスクをリストから探し、ダブルクリックしてプロパティを開きます。
  9. [全般]タブの最下部にある[最上位の特権で実行する]にチェックを入れます。
  10. [OK]を押して閉じれば設定完了です。

方法2:スクリプトの先頭に[管理者権限への昇格コード]を書く

すでにスタートアップフォルダ(Shell:startup)にファイルを配置している場合、スクリプトのコードの一番最初(1行目)に以下のコードを貼り付けることで、起動時に自動で管理者権限への昇格を要求させることができます。

;管理者権限で実行されていない場合、管理者として再起動する
if not A_IsAdmin
{
    Run *RunAs "%A_ScriptFullPath%"
    ExitApp
}
; ---ここから下にあなたのスクリプトを記述してください---

💡注意点

この方法の場合、PC起動時に[このアプリがデバイスに変更を加えることを許可しますか?]というUACのポップアップ画面(はい/いいえ)が毎回表示されます。 完全に全自動でサイレント起動させたい場合は、方法1(タスクスケジューラ)を行ってください。 今回はどちらの方法で進めたいですか? もし設定中にエラーが出る、あるいはタスクスケジューラの設定手順で迷う部分があれば、具体的な状況を教えてください。 詳しくサポートします!

AutoHotkey 2.0でLIFOのテキストスタックシステムを実現する|スクリプト

  • このスクリプトは、WZエディターでテキストスタックに読み込んだ文字列をLIFOで吐き出すためのツールなので、万能ではありません。
  • ; [Win + V] : スタックから最新のテキストを取り出して貼り付け(ポップ)
  • ; [Win + Shift + V] : 現在蓄積されている履歴の一覧を確認する
  • ; [Win + C] : 選択中のテキストを「現在のクリップボードを維持したまま」テキストスタックに追加
#Requires AutoHotkey v2.0

; 保持する最大履歴数
global maxHistory := 1000
global historyStack := []
global isInternalAction := false

OnClipboardChange(ClipChanged)

ClipChanged(dataType) {
    global historyStack, isInternalAction
    if (isInternalAction) {
        isInternalAction := false
        return
    }
    if (dataType = 1) {
        text := A_Clipboard
        if (text = "")
            return
        
        ; 直前と同じ内容の連続コピーは重複して積まない
        if (historyStack.Length > 0 && historyStack[historyStack.Length] = text)
            return
            
        historyStack.Push(text)
        if (historyStack.Length > maxHistory)
            historyStack.RemoveAt(1)
    }
}

; [Win + V] : スタックから最新のテキストを取り出して貼り付け(ポップ)
#v:: {
    global historyStack, isInternalAction
    if (historyStack.Length > 0) {
        isInternalAction := true
        A_Clipboard := historyStack.Pop()
        Sleep(50)
        Send("^v")
    } else {
        ToolTip("履歴がありません")
        SetTimer(() => ToolTip(), -1000)
    }
}

; [Win + Shift + V] : 現在蓄積されている履歴の一覧を確認する
#+v:: {
    global historyStack
    if (historyStack.Length = 0) {
        ToolTip("履歴は空です")
        SetTimer(() => ToolTip(), -1000)
        return
    }
    
    listStr := "--- クリップボード履歴 (LIFO) ---\n"
    Loop historyStack.Length {
        idx := historyStack.Length - A_Index + 1
        item := historyStack[idx]
        if (StrLen(item) > 30)
            item := SubStr(item, 1, 30) . "..."
        listStr .= idx ": " . item . "\n"
    }
    ToolTip(listStr)
    SetTimer(() => ToolTip(), -4000)
}

; [Win + C] : 選択中のテキストを「現在のクリップボードを維持したまま」テキストスタックに追加
#c:: {
    global historyStack, maxHistory
    
    ; 1. 現在のクリップボード内容を一時退避
    oldClip := A_Clipboard
    A_Clipboard := ""
    
    ; 2. 選択部分を一時的にコピー
    Send("^c")
    
    ; 3. クリップボードにデータが入るのを待つ (最大0.5秒)
    if ClipWait(0.5) {
        selectedText := A_Clipboard
        
        ; 4. クリップボードを元の状態に即座に戻す
        A_Clipboard := oldClip
        
        if (selectedText != "") {
            ; 連続重複チェック
            if (historyStack.Length > 0 && historyStack[historyStack.Length] = selectedText) {
                ToolTip("直前と同じテキストです")
            } else {
                historyStack.Push(selectedText)
                if (historyStack.Length > maxHistory)
                    historyStack.RemoveAt(1)
                
                ; 追加されたことを短いツールチップで通知
                preview := StrLen(selectedText) > 20 ? SubStr(selectedText, 1, 20) . "..." : selectedText
                ToolTip("スタックに追加: " . preview)
            }
            SetTimer(() => ToolTip(), -1500)
        }
    } else {
        ; コピー失敗時は元に戻す
        A_Clipboard := oldClip
        ToolTip("テキストが選択されていません")
        SetTimer(() => ToolTip(), -1000)
    }
}
◀
 

↑