🟩 もくじ
AutoHotkey 2.0でLIFOのテキストスタックシステムを実現する(VZエディタやWZエディタと同じLIFOを実現する仕組みの実現)
- このスクリプトを意図通りに動作させるには、管理者権限で実行する必要があります。
- AutoHotkeyのファイルをスタートメニューに置くだけでは、PC起動時に管理者権限で実行されません。
- スタートアップフォルダにショートカットを置くだけでは、セキュリティ(UAC)の制限で管理者権限が解除されるか、エラーになってしまいます。 これを解決するための最も確実で安全な2つの方法を解説します。
方法1:Windowsの[タスクスケジューラ]を使う(★★★最も推奨)
Windowsの標準機能である[タスクスケジューラ]を使えば、PC起動時にログインしたタイミングで、UACの警告なしで管理者権限のままスクリプトを自動起動できます。
- キーボードのWin + Rを押し、taskschd.mscと入力してEnterを押します。
- 右側の操作パネルから[基本タスクの作成]をクリックします。
- 名前に分かりやすい名前(例:AHK_Startup)を入力し、[次へ]を進めます。
- トリガーで[ログオン時]を選択し、[次へ]を進めます。
- 操作で[プログラムの開始]を選択し、[次へ]を進めます。
- プログラム/スクリプトの[参照]ボタンから、実行したいAutoHotkeyスクリプト(.ahkファイルまたはコンパイルした.exeファイル)を選択します。
- [完了]をクリックしてタスクを一度作成します。
- 作成したタスクをリストから探し、ダブルクリックしてプロパティを開きます。
- [全般]タブの最下部にある[最上位の特権で実行する]にチェックを入れます。
- [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)
}
}