#include <Misc.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
; ── 설정 ──
Global Const $OVERLAY_FONT_SIZE = 36
Global Const $OVERLAY_FONT_NAME = "맑은 고딕"
Global Const $OVERLAY_BG_COLOR = 0xCC000000 ; 반투명 검정 배경 (AARRGGBB)
Global Const $OVERLAY_TEXT_COLOR = 0xFFFFFF00 ; 노란색 텍스트 (AARRGGBB)
Global Const $OVERLAY_PADDING = 20
Global Const $OVERLAY_DISPLAY_MS = 3000 ; 표시 시간 (ms)
Global Const $OVERLAY_CHECK_INTERVAL = 50 ; 키 체크 간격 (ms)
_MAIN()
Func _MAIN()
Local $aPressedKeys = _GET_PRESSED_MOD_KEYS()
If $aPressedKeys[0] = 0 Then Exit ; 눌린 키 없으면 종료
Local $sText = _BUILD_DISPLAY_TEXT($aPressedKeys)
_SHOW_OVERLAY($sText)
EndFunc
; ── 현재 눌린 수정키 검사 ──
Func _GET_PRESSED_MOD_KEYS()
; [0] = 개수, [1]~[n] = 키 이름
Local $aResult[9] ; 최대 8개 + 카운트
$aResult[0] = 0
; Left/Right Shift (VK_LSHIFT=A0, VK_RSHIFT=A1)
If _IsPressed("A0") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "L-Shift"
EndIf
If _IsPressed("A1") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "R-Shift"
EndIf
; Left/Right Ctrl (VK_LCONTROL=A2, VK_RCONTROL=A3)
If _IsPressed("A2") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "L-Ctrl"
EndIf
If _IsPressed("A3") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "R-Ctrl"
EndIf
; Left/Right Alt (VK_LMENU=A4, VK_RMENU=A5)
If _IsPressed("A4") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "L-Alt"
EndIf
If _IsPressed("A5") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "R-Alt"
EndIf
; Left/Right Win (VK_LWIN=5B, VK_RWIN=5C)
If _IsPressed("5B") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "L-Win"
EndIf
If _IsPressed("5C") Then
$aResult[0] += 1
$aResult[$aResult[0]] = "R-Win"
EndIf
Return $aResult
EndFunc
; ── 표시할 텍스트 조합 ──
Func _BUILD_DISPLAY_TEXT($aPressedKeys)
Local $sText = ""
For $i = 1 To $aPressedKeys[0]
If $sText <> "" Then $sText &= " + "
$sText &= $aPressedKeys[$i]
Next
Return "눌린 키: " & $sText
EndFunc
; ── GDI+ 레이어드 오버레이 표시 ──
Func _SHOW_OVERLAY($sText)
_GDIPlus_Startup()
; 텍스트 크기 측정
Local $hMeasureBmp = _GDIPlus_BitmapCreateFromScan0(1, 1)
Local $hMeasureGfx = _GDIPlus_ImageGetGraphicsContext($hMeasureBmp)
Local $hFontFamily = _GDIPlus_FontFamilyCreate($OVERLAY_FONT_NAME)
Local $hFont = _GDIPlus_FontCreate($hFontFamily, $OVERLAY_FONT_SIZE, 1) ; 1=Bold
Local $hFormat = _GDIPlus_StringFormatCreate()
Local $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0)
Local $aInfo = _GDIPlus_GraphicsMeasureString($hMeasureGfx, $sText, $hFont, $tLayout, $hFormat)
Local $iTextW = Ceiling(DllStructGetData($aInfo[0], "Width"))
Local $iTextH = Ceiling(DllStructGetData($aInfo[0], "Height"))
_GDIPlus_GraphicsDispose($hMeasureGfx)
_GDIPlus_BitmapDispose($hMeasureBmp)
; 오버레이 크기
Local $iW = $iTextW + ($OVERLAY_PADDING * 2)
Local $iH = $iTextH + ($OVERLAY_PADDING * 2)
Local $iCorner = 16 ; 둥근 모서리 반지름
; 화면 중앙 좌표
Local $iScreenW = @DesktopWidth
Local $iScreenH = @DesktopHeight
Local $iX = Int(($iScreenW - $iW) / 2)
Local $iY = Int(($iScreenH - $iH) / 2)
; 레이어드 윈도우 생성 (투명, 항상위, 클릭통과)
Local $hGUI = GUICreate("", $iW, $iH, $iX, $iY, _
$WS_POPUP, _
BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST, $WS_EX_TRANSPARENT, $WS_EX_TOOLWINDOW))
; GDI+ 비트맵에 그리기
Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hGraphics, 4) ; AntiAlias
_GDIPlus_GraphicsSetTextRenderingHint($hGraphics, 5) ; ClearType
; 둥근 사각형 배경
Local $hPath = _GDIPlus_PathCreate()
_GDIPlus_PathAddArc($hPath, 0, 0, $iCorner * 2, $iCorner * 2, 180, 90)
_GDIPlus_PathAddArc($hPath, $iW - $iCorner * 2, 0, $iCorner * 2, $iCorner * 2, 270, 90)
_GDIPlus_PathAddArc($hPath, $iW - $iCorner * 2, $iH - $iCorner * 2, $iCorner * 2, $iCorner * 2, 0, 90)
_GDIPlus_PathAddArc($hPath, 0, $iH - $iCorner * 2, $iCorner * 2, $iCorner * 2, 90, 90)
_GDIPlus_PathCloseFigure($hPath)
Local $hBgBrush = _GDIPlus_BrushCreateSolid($OVERLAY_BG_COLOR)
_GDIPlus_GraphicsFillPath($hGraphics, $hPath, $hBgBrush)
; 텍스트 그리기
Local $hTextBrush = _GDIPlus_BrushCreateSolid($OVERLAY_TEXT_COLOR)
Local $tTextRect = _GDIPlus_RectFCreate($OVERLAY_PADDING, $OVERLAY_PADDING, $iTextW, $iTextH)
_GDIPlus_GraphicsDrawStringEx($hGraphics, $sText, $hFont, $tTextRect, $hFormat, $hTextBrush)
; 레이어드 윈도우에 적용
Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
Local $hDC_Screen = _WinAPI_GetDC(0)
Local $hDC_Mem = _WinAPI_CreateCompatibleDC($hDC_Screen)
Local $hOldBmp = _WinAPI_SelectObject($hDC_Mem, $hHBitmap)
Local $tSize = DllStructCreate("long X;long Y")
DllStructSetData($tSize, "X", $iW)
DllStructSetData($tSize, "Y", $iH)
Local $tPos = DllStructCreate("long X;long Y")
DllStructSetData($tPos, "X", $iX)
DllStructSetData($tPos, "Y", $iY)
Local $tSrcPos = DllStructCreate("long X;long Y")
DllStructSetData($tSrcPos, "X", 0)
DllStructSetData($tSrcPos, "Y", 0)
Local $tBlend = DllStructCreate("byte Op;byte Flags;byte Alpha;byte Format")
DllStructSetData($tBlend, "Op", 0) ; AC_SRC_OVER
DllStructSetData($tBlend, "Flags", 0)
DllStructSetData($tBlend, "Alpha", 255) ; 전체 알파 (비트맵 자체 알파 사용)
DllStructSetData($tBlend, "Format", 1) ; AC_SRC_ALPHA
_WinAPI_UpdateLayeredWindow($hGUI, $hDC_Screen, $tPos, $tSize, $hDC_Mem, $tSrcPos, 0, $tBlend, 2)
GUISetState(@SW_SHOWNOACTIVATE, $hGUI)
; ── 표시 유지: 키가 떼지거나 시간 초과 시 종료 ──
Local $iStart = TimerInit()
While TimerDiff($iStart) < $OVERLAY_DISPLAY_MS
; 모든 수정키가 떼졌는지 체크
If Not _IsPressed("A0") And Not _IsPressed("A1") And _
Not _IsPressed("A2") And Not _IsPressed("A3") And _
Not _IsPressed("A4") And Not _IsPressed("A5") And _
Not _IsPressed("5B") And Not _IsPressed("5C") Then
ExitLoop
EndIf
Sleep($OVERLAY_CHECK_INTERVAL)
WEnd
; ── 리소스 정리 ──
_WinAPI_SelectObject($hDC_Mem, $hOldBmp)
_WinAPI_DeleteDC($hDC_Mem)
_WinAPI_ReleaseDC(0, $hDC_Screen)
_WinAPI_DeleteObject($hHBitmap)
_GDIPlus_BrushDispose($hTextBrush)
_GDIPlus_BrushDispose($hBgBrush)
_GDIPlus_PathDispose($hPath)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFontFamily)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()
GUIDelete($hGUI)
EndFunc