| name | julien-ref-ahk-v2 |
| description | Best practices AutoHotkey v2. Use when writing AHK v2 scripts - covers global variable declarations, SetTimer usage, event handlers, and GUI positioning. |
| triggers | raccourci clavier windows, automatiser une tâche windows, mon script ahk ne marche pas, aide pour mon script ahk, help with my ahk script, create a hotkey, autohotkey v2, ahk v2, ahk2, autohotkey tutorial |
AutoHotkey v2 - Best Practices pour LLM
RÈGLE CRITIQUE - VARIABLES GLOBALES
DÉCLARATION OBLIGATOIRE DANS CHAQUE FONCTION
; INCORRECT - Cause erreur "variable not assigned"
SomeFunction() {
g_MyGlobalVar := "value" ; ERREUR!
}
; CORRECT - Déclaration explicite requise
SomeFunction() {
global g_MyGlobalVar ; OBLIGATOIRE
g_MyGlobalVar := "value" ; OK
}
LISTE COMPLÈTE DES VARIABLES À DÉCLARER
FunctionUsingGlobals() {
; Déclarer TOUTES les variables globales utilisées
global g_AppVersion, g_IsInitialized, g_ConfigFile
global g_CachedPhrases, g_SavedSelections, g_CurrentProject
; Maintenant on peut les utiliser
g_IsInitialized := true
return g_AppVersion
}
STRUCTURE MODULAIRE AUTOHOTKEY V2
En-tête Standard
; Module.ahv2 - Description du module
; Encodage : UTF-8 avec BOM
; AutoHotkey v2
; Variables globales du module (si nécessaire)
global g_ModuleVar := ""
Ordre d'Inclusion Critique
; 1. Configuration TOUJOURS EN PREMIER
#Include "Config\Settings.ah2"
#Include "Config\Paths.ah2"
; 2. Modules Core
#Include "Core\Logger.ah2"
#Include "Core\FileManager.ah2"
; 3. Modules Features (qui dépendent de Core)
#Include "Features\PhraseManager.ah2"
; 4. GUI en dernier
#Include "GUI\MainInterface.ah2"
TIMERS ET ÉVÉNEMENTS - NOUVELLES ERREURS CRITIQUES
SetTimer vs Timer() - ERREUR CRITIQUE
; INCORRECT - Timer() n'existe pas en AHK v2
g_TooltipTimer := Timer(GUI_TooltipCheckMouse, 100)
g_TooltipTimer.Start()
; CORRECT - Utiliser SetTimer
SetTimer(GUI_TooltipCheckMouse, 100)
; CORRECT - Arrêter timer
SetTimer(GUI_TooltipCheckMouse, 0) ; 0 = arrêter
; CORRECT - Timer périodique avec variable de contrôle
g_TimerActive := true
SetTimer(MyFunction, 100)
StopMyTimer() {
global g_TimerActive
g_TimerActive := false
SetTimer(MyFunction, 0)
}
Event Handlers GUI - Signatures Correctes
; INCORRECT - Signature trop spécifique peut échouer
GUI_HandleResize(GuiObj, MinMax, Width, Height) {
; Cette signature peut ne pas correspondre à l'événement réel
}
; CORRECT - Signature flexible avec paramètres variables
GUI_HandleResize(*) {
; Récupérer dimensions via la GUI elle-même
global g_MainGui
g_MainGui.GetPos(, , &Width, &Height)
; ... traitement
}
; CORRECT - Event handlers standards
g_MainGui.OnEvent("Close", (*) => GUI_Hide())
g_MainGui.OnEvent("Size", GUI_HandleResize) ; Fonction sans parenthèses
g_MainGui.OnEvent("Escape", (*) => GUI_Hide())
ListView Event Handlers
; CORRECT - Signatures standard ListView
ListView_OnItemCheck(ListViewObj, Item, Checked) {
; Item = numéro ligne, Checked = true/false
}
ListView_OnItemFocus(ListViewObj, Item) {
; Item = numéro ligne qui a le focus
}
; CORRECT - Assignment
g_ListView.OnEvent("ItemCheck", ListView_OnItemCheck)
g_ListView.OnEvent("ItemFocus", ListView_OnItemFocus)
INTERFACE UTILISATEUR - POSITIONNEMENT CRITIQUE
Calculs de Positionnement d'Interface
; PROBLÈME COURANT - Interface mal dimensionnée
CreateGUI() {
; Boutons positionnés trop bas, pas visibles
g_Button1 := g_Gui.Add("Button", "x10 y450 w80 h30", "OK")
g_ListView := g_Gui.Add("ListView", "x10 y70 w620 h400", cols)
; Total height = 70 + 400 + 30 = 500px mais fenêtre fait 480px
}
; SOLUTION - Calculs cohérents
CreateGUI() {
; Définir dimensions fenêtre d'abord
windowHeight := 450
headerHeight := 70
footerHeight := 80 ; boutons + marge
; ListView adaptatif
listViewHeight := windowHeight - headerHeight - footerHeight
g_ListView := g_Gui.Add("ListView", "x10 y" . headerHeight . " w620 h" . listViewHeight, cols)
; Boutons dans footer calculé
buttonY := headerHeight + listViewHeight + 10
g_Button1 := g_Gui.Add("Button", "x10 y" . buttonY . " w80 h30", "OK")
}
GESTION DONNÉES STRUCTURÉES ET NUMÉROTATION
Objets avec Propriétés Multiples
; STRUCTURE ENRICHIE POUR CACHE
Cache_LoadData() {
global g_CachedPhrases
currentTitleNumber := 0
currentPhraseNumber := 0
; Créer objets avec métadonnées complètes
for lineNum, currentLine in lines {
if (InStr(currentLine, ";;#") = 1) {
currentTitleNumber++
currentPhraseNumber := 0
titleText := Trim(SubStr(currentLine, 4))
g_CachedPhrases.Push({
Type: "Title",
Text: "[" . currentTitleNumber . "] === " . titleText . " ===",
OriginalText: titleText,
TitleNumber: currentTitleNumber
})
} else {
currentPhraseNumber++
g_CachedPhrases.Push({
Type: "Phrase",
Text: "[" . currentTitleNumber . "." . currentPhraseNumber . "] " . currentLine,
OriginalText: currentLine,
TitleNumber: currentTitleNumber,
PhraseNumber: currentPhraseNumber
})
}
}
}
Accès Propriétés Sécurisé
GUI_ProcessPhrases() {
global g_CachedPhrases
for phraseObj in g_CachedPhrases {
; Vérification existence propriété
originalText := phraseObj.HasProp("OriginalText") ? phraseObj.OriginalText : phraseObj.Text
; Traitement conditionnel par type
if (phraseObj.Type = "Title") {
; Traitement spécial titres
} else if (phraseObj.Type = "Phrase") {
; Traitement phrases normales
}
}
}
ERREURS CRITIQUES À ÉVITER
- Variables globales sans déclaration - Cause systématiquement des erreurs
- Timer() au lieu de SetTimer - Timer() n'existe pas en AutoHotkey v2
- Event handlers avec signatures incorrectes - Utiliser (*) pour flexibilité
- Calculs interface incohérents - Boutons hors limites fenêtre
- Chemins relatifs incorrects dans les tests
- Ordre d'inclusion - Settings.ah2 TOUJOURS en premier
- Initialisation dans le désordre - Logger avant Cache
- Variables non initialisées - Toujours initialiser avant usage
CONVENTIONS DE NOMMAGE
; Variables globales
global g_AppVersion := "1.0.0"
global g_IsInitialized := false
global g_ConfigFile := ""
; Fonctions - Module_Action
Logger_Write()
Cache_Initialize()
PhraseManager_LoadData()
; Constantes en majuscules
global MAX_CACHE_SIZE := 1000
global DEFAULT_TIMEOUT := 5000
CHECKLIST VALIDATION
Avant de déployer un script AutoHotkey v2 :
- Toutes les fonctions ont des déclarations
globalappropriées - SetTimer utilisé correctement (pas Timer())
- Event handlers avec signatures flexibles (*)
- Calculs interface cohérents (boutons dans limites fenêtre)
- Ordre d'inclusion respecté (Config → Core → Features → GUI)
- Chemins relatifs corrects dans les tests (
..\..\) - Variables globales initialisées avant usage
- Tests de compilation passent sans erreur
- Gestion d'erreurs implémentée
- Logging configuré pour debug