; ============================================================ ; SASP — Superposition en jeu (style overlay NVIDIA / Radeon) ; AutoHotkey v2 — https://www.autohotkey.com (installer la version 2) ; ; Alt+Z Afficher / cacher la fenêtre SASP par-dessus le jeu ; Alt+X UNE touche : photographie l'écran du jeu et l'envoie dans SASP (la fiche du labo est détectée et découpée toute seule) ; Alt+S Coller ce qu'il y a dans le presse-papiers (ex. capture faite avec Win+Shift+S) ; Alt+C Collage automatique ON / OFF : chaque Win+Shift+S part tout seul dans le dossier ; Alt+V Transparence : 100 % → 90 % → 80 % ; Alt+B Changer de côté (droite / gauche) ; (F8 évité : c'est la console de FiveM) ; ; Le jeu doit être en « Plein écran fenêtré » (borderless) dans les paramètres de GTA. ; Première ouverture : connecte-toi une fois avec ta carte d'agent dans la fenêtre SASP. ; ============================================================ #Requires AutoHotkey v2.0 #SingleInstance Force SetTitleMatchMode "RegEx" URL := "https://eli-sasp.fr/scientifique.html?overlay=1" LARGEUR := 480 ; fenêtre SASP en mode application : titre « SASP — … » sans « Chrome » ni « Edge » à la fin FENETRE := "^SASP —(?!.*(Chrome|Edge)$)" transparence := [255, 230, 205] idxTransp := 1 cote := "droite" autoCollage := true dernierCollage := 0 jeu := 0 ; dernière fenêtre active avant l'affichage de SASP (le jeu) A_IconTip := "SASP — Superposition (Alt+Z)" TrayTip "Alt+X : capture du jeu → SASP (une touche)`nAlt+Z : afficher / cacher`nAlt+C : collage auto des Win+Shift+S (activé)", "SASP — Superposition prête" Navigateur() { for chemin in [ EnvGet("ProgramFiles") "\Google\Chrome\Application\chrome.exe", EnvGet("ProgramFiles(x86)") "\Google\Chrome\Application\chrome.exe", EnvGet("LocalAppData") "\Google\Chrome\Application\chrome.exe", EnvGet("ProgramFiles(x86)") "\Microsoft\Edge\Application\msedge.exe", EnvGet("ProgramFiles") "\Microsoft\Edge\Application\msedge.exe"] if FileExist(chemin) return chemin return "" } Placer(hwnd) { global LARGEUR, cote MonitorGetWorkArea(MonitorGetPrimary(), &g, &h, &d, &b) x := (cote = "droite") ? d - LARGEUR - 12 : g + 12 WinRestore hwnd WinMove x, h + 12, LARGEUR, b - h - 24, hwnd } FenetreSASP() { global FENETRE return WinExist(FENETRE) } Ouvrir() { global URL, LARGEUR, transparence, idxTransp hwnd := FenetreSASP() if !hwnd { nav := Navigateur() if (nav = "") { MsgBox "Chrome ou Edge introuvable.", "SASP" return 0 } Run '"' nav '" --app="' URL '" --window-size=' LARGEUR ',900' if !WinWait(FENETRE, , 15) { TrayTip "La fenêtre SASP n'a pas répondu. Réessaie Alt+Z.", "SASP" return 0 } hwnd := FenetreSASP() Placer(hwnd) } WinSetAlwaysOnTop 1, hwnd WinSetTransparent transparence[idxTransp], hwnd if WinGetMinMax(hwnd) = -1 WinRestore hwnd return hwnd } MemoriserJeu() { global jeu actif := WinExist("A") if actif && actif != FenetreSASP() jeu := actif } RevenirAuJeu() { global jeu if jeu && WinExist(jeu) WinActivate jeu } ; ---------- Alt+Z : afficher / cacher ---------- !z:: { hwnd := FenetreSASP() if hwnd && WinGetMinMax(hwnd) != -1 && WinActive(hwnd) { WinMinimize hwnd RevenirAuJeu() return } MemoriserJeu() if hwnd := Ouvrir() WinActivate hwnd } ; ---------- Alt+X : capture de l'écran + envoi, en une touche ---------- !x:: CaptureEcran() !s:: CollerCapture() CaptureEcran(*) { global dernierCollage, transparence, idxTransp MemoriserJeu() hwnd := Ouvrir() if !hwnd return ; La fenêtre SASP reste visible : tant qu'une fenêtre est par-dessus le jeu, Windows recompose l'écran ; à chaque image. Sans elle, le jeu passe en « flip direct » et la capture renvoie une ancienne image figée. WinSetAlwaysOnTop 1, hwnd Sleep 250 ok := EcranVersPressePapiers() if !ok { ToolTip "Capture impossible" SetTimer () => ToolTip(), -1500 return } dernierCollage := Sequence() ; évite que le collage automatique la colle une 2e fois Envoyer(hwnd, true) } ; copie l'écran principal dans le presse-papiers (image) EcranVersPressePapiers() { MonitorGet(MonitorGetPrimary(), &g, &h, &d, &b) w := d - g, ht := b - h hdcEcran := DllCall("GetDC", "Ptr", 0, "Ptr") hdcMem := DllCall("CreateCompatibleDC", "Ptr", hdcEcran, "Ptr") hbm := DllCall("CreateCompatibleBitmap", "Ptr", hdcEcran, "Int", w, "Int", ht, "Ptr") ancien := DllCall("SelectObject", "Ptr", hdcMem, "Ptr", hbm, "Ptr") DllCall("BitBlt", "Ptr", hdcMem, "Int", 0, "Int", 0, "Int", w, "Int", ht, "Ptr", hdcEcran, "Int", g, "Int", h, "UInt", 0x40CC0020) DllCall("SelectObject", "Ptr", hdcMem, "Ptr", ancien) DllCall("DeleteDC", "Ptr", hdcMem) DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdcEcran) if !DllCall("OpenClipboard", "Ptr", A_ScriptHwnd) { DllCall("DeleteObject", "Ptr", hbm) return false } DllCall("EmptyClipboard") ok := DllCall("SetClipboardData", "UInt", 2, "Ptr", hbm, "Ptr") ; CF_BITMAP : le presse-papiers devient propriétaire DllCall("CloseClipboard") if !ok DllCall("DeleteObject", "Ptr", hbm) return !!ok } ; met la fenêtre SASP devant, Ctrl+V, puis revient au jeu Envoyer(hwnd, retour) { WinActivate hwnd if !WinWaitActive(hwnd, , 2) return Sleep 300 ; laisse Chrome prendre le focus avant Ctrl+V Send "^v" Sleep 400 if retour RevenirAuJeu() ToolTip "Capture envoyée au dossier SASP" SetTimer () => ToolTip(), -1800 } CollerCapture(*) { global dernierCollage ; attendre que la capture soit vraiment arrivée dans le presse-papiers (sinon c'est l'ancienne qui part) if !AttendreImage() { ToolTip "Pas d'image dans le presse-papiers" SetTimer () => ToolTip(), -1500 return } if (Sequence() = dernierCollage) ; déjà collée return dejaDansSASP := (hwnd := FenetreSASP()) && WinActive(hwnd) if !dejaDansSASP MemoriserJeu() hwnd := Ouvrir() if !hwnd return dernierCollage := Sequence() Envoyer(hwnd, !dejaDansSASP) } Sequence() => DllCall("GetClipboardSequenceNumber", "UInt") ImageDispo() => DllCall("IsClipboardFormatAvailable", "UInt", 8) || DllCall("IsClipboardFormatAvailable", "UInt", 2) ; attend que le presse-papiers contienne une image et ne bouge plus pendant 400 ms AttendreImage() { debut := A_TickCount while (A_TickCount - debut < 4000) { s := Sequence() Sleep 400 if (s = Sequence() && ImageDispo()) return true } return ImageDispo() } ; ---------- Alt+C : collage automatique des captures ---------- !c:: { global autoCollage autoCollage := !autoCollage ToolTip "Collage automatique : " (autoCollage ? "activé" : "désactivé") SetTimer () => ToolTip(), -1800 } OnClipboardChange SurPressePapiers SurPressePapiers(type) { global autoCollage ; type 2 = image (capture Win+Shift+S) ; uniquement si la fenêtre SASP est ouverte hwnd := FenetreSASP() ; la capture Windows met parfois plusieurs images à la suite : on attend que le presse-papiers soit stable global dernierCollage ; marche aussi quand la fenêtre SASP est au premier plan (fiche photo ouverte, etc.) if (type = 2 && autoCollage && hwnd && Sequence() != dernierCollage) SetTimer CollerCapture, -300 ; relancé à chaque changement : un seul collage, une fois la capture stable } ; ---------- Alt+V : transparence ; Alt+B : changer de côté ---------- !v:: { global idxTransp, transparence idxTransp := Mod(idxTransp, transparence.Length) + 1 if hwnd := FenetreSASP() WinSetTransparent transparence[idxTransp], hwnd ToolTip "Opacité : " Round(transparence[idxTransp] / 255 * 100) " %" SetTimer () => ToolTip(), -1200 } !b:: { global cote cote := (cote = "droite") ? "gauche" : "droite" if hwnd := FenetreSASP() Placer(hwnd) }