다른 명령
플랫 버튼 스타일
- 1. BS_FLAT 스타일 (가장 간단)
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
$hGUI = GUICreate("Flat Button", 300, 200)
GUISetBkColor(0xFFFFFF)
$hBtn = GUICtrlCreateButton("클릭", 50, 50, 200, 40, $BS_FLAT)
GUISetState()
While GUIGetMsg() <> $GUI_EVENT_CLOSE
WEnd
3D 테두리가 제거되지만, 마우스 오버 시 테두리가 살아나서 완전한 플랫은 아닙니다.
- 2. Label + 색상 조합 (완전 플랫)
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
$hGUI = GUICreate("Flat Button", 400, 300)
GUISetBkColor(0xFFFFFF)
; 버튼처럼 동작하는 Label
$hBtn1 = _CREATE_FLAT_BUTTON("저장", 30, 50, 150, 45, 0x2196F3, 0xFFFFFF)
$hBtn2 = _CREATE_FLAT_BUTTON("취소", 210, 50, 150, 45, 0xF44336, 0xFFFFFF)
$hBtn3 = _CREATE_FLAT_BUTTON("설정", 30, 120, 150, 45, 0x4CAF50, 0xFFFFFF)
$hBtn4 = _CREATE_FLAT_BUTTON("닫기", 210, 120, 150, 45, 0x757575, 0xFFFFFF)
GUISetState()
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $hBtn1
MsgBox(0, "", "저장 클릭")
Case $hBtn2
MsgBox(0, "", "취소 클릭")
Case $hBtn3
MsgBox(0, "", "설정 클릭")
Case $hBtn4
MsgBox(0, "", "닫기 클릭")
EndSwitch
WEnd
Func _CREATE_FLAT_BUTTON($sText, $iX, $iY, $iW, $iH, $iBgColor, $iFontColor)
Local $hLabel = GUICtrlCreateLabel($sText, $iX, $iY, $iW, $iH, _
BitOR($SS_CENTER, $SS_CENTERIMAGE))
GUICtrlSetBkColor($hLabel, $iBgColor)
GUICtrlSetColor($hLabel, $iFontColor)
GUICtrlSetFont($hLabel, 11, 600, 0, "맑은 고딕")
GUICtrlSetCursor($hLabel, 0) ; 손가락 커서
Return $hLabel
EndFunc
- 3. GDI+ Owner-Draw (호버 효과 포함)
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <StaticConstants.au3>
Global Const $FLAT_COLOR_NORMAL = 0xFF2196F3 ; 파란색
Global Const $FLAT_COLOR_HOVER = 0xFF1976D2 ; 진한 파란색
Global Const $FLAT_COLOR_PRESS = 0xFF0D47A1 ; 더 진한 파란색
Global Const $FLAT_COLOR_TEXT = 0xFFFFFFFF ; 흰색
Global $g_aBtns[0][6] ; [n][CtrlID, X, Y, W, H, Text]
Global $g_iHoverIdx = -1
Global $g_iPressIdx = -1
Global $g_hGUI
_GDIPlus_Startup()
$g_hGUI = GUICreate("GDI+ Flat Buttons", 400, 300)
GUISetBkColor(0xF5F5F5)
; GDI+ 그리기용 Pic 컨트롤 (전체 영역)
Global $g_hPic = GUICtrlCreatePic("", 0, 0, 400, 300)
GUICtrlSetState($g_hPic, $GUI_DISABLE)
; 버튼 등록
_ADD_FLAT_BUTTON(30, 50, 150, 45, "저장")
_ADD_FLAT_BUTTON(210, 50, 150, 45, "취소")
_ADD_FLAT_BUTTON(30, 120, 150, 45, "설정")
_ADD_FLAT_BUTTON(210, 120, 150, 45, "닫기")
_DRAW_ALL_BUTTONS()
GUISetState()
GUIRegisterMsg($WM_MOUSEMOVE, "_WM_MOUSEMOVE")
GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN")
GUIRegisterMsg($WM_LBUTTONUP, "_WM_LBUTTONUP")
While GUIGetMsg() <> $GUI_EVENT_CLOSE
WEnd
_GDIPlus_Shutdown()
; ── 버튼 추가 ──
Func _ADD_FLAT_BUTTON($iX, $iY, $iW, $iH, $sText)
Local $iIdx = UBound($g_aBtns)
ReDim $g_aBtns[$iIdx + 1][6]
$g_aBtns[$iIdx][0] = $iIdx
$g_aBtns[$iIdx][1] = $iX
$g_aBtns[$iIdx][2] = $iY
$g_aBtns[$iIdx][3] = $iW
$g_aBtns[$iIdx][4] = $iH
$g_aBtns[$iIdx][5] = $sText
EndFunc
; ── 전체 버튼 그리기 ──
Func _DRAW_ALL_BUTTONS()
Local $hBitmap = _GDIPlus_BitmapCreateFromScan0(400, 300)
Local $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hGfx, 4)
_GDIPlus_GraphicsSetTextRenderingHint($hGfx, 5)
_GDIPlus_GraphicsClear($hGfx, 0xFFF5F5F5)
Local $hFontFamily = _GDIPlus_FontFamilyCreate("맑은 고딕")
Local $hFont = _GDIPlus_FontCreate($hFontFamily, 12, 1)
Local $hFormat = _GDIPlus_StringFormatCreate()
_GDIPlus_StringFormatSetAlign($hFormat, 1) ; 가로 중앙
_GDIPlus_StringFormatSetLineAlign($hFormat, 1) ; 세로 중앙
Local $hTextBrush = _GDIPlus_BrushCreateSolid($FLAT_COLOR_TEXT)
For $i = 0 To UBound($g_aBtns) - 1
; 상태별 색상 결정
Local $iColor = $FLAT_COLOR_NORMAL
If $i = $g_iPressIdx Then
$iColor = $FLAT_COLOR_PRESS
ElseIf $i = $g_iHoverIdx Then
$iColor = $FLAT_COLOR_HOVER
EndIf
; 둥근 사각형 배경
Local $hPath = _GDIPlus_PathCreate()
Local $r = 8 ; 둥근 반지름
Local $bX = $g_aBtns[$i][1], $bY = $g_aBtns[$i][2]
Local $bW = $g_aBtns[$i][3], $bH = $g_aBtns[$i][4]
_GDIPlus_PathAddArc($hPath, $bX, $bY, $r * 2, $r * 2, 180, 90)
_GDIPlus_PathAddArc($hPath, $bX + $bW - $r * 2, $bY, $r * 2, $r * 2, 270, 90)
_GDIPlus_PathAddArc($hPath, $bX + $bW - $r * 2, $bY + $bH - $r * 2, $r * 2, $r * 2, 0, 90)
_GDIPlus_PathAddArc($hPath, $bX, $bY + $bH - $r * 2, $r * 2, $r * 2, 90, 90)
_GDIPlus_PathCloseFigure($hPath)
Local $hBrush = _GDIPlus_BrushCreateSolid($iColor)
_GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_PathDispose($hPath)
; 텍스트
Local $tRect = _GDIPlus_RectFCreate($bX, $bY, $bW, $bH)
_GDIPlus_GraphicsDrawStringEx($hGfx, $g_aBtns[$i][5], $hFont, $tRect, $hFormat, $hTextBrush)
Next
; Pic에 적용
Local $hHBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
_WinAPI_DeleteObject(GUICtrlSendMsg($g_hPic, 0x0172, 0, $hHBmp)) ; STM_SETIMAGE
_WinAPI_DeleteObject($hHBmp)
_GDIPlus_BrushDispose($hTextBrush)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFontFamily)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_BitmapDispose($hBitmap)
EndFunc
; ── 마우스 위치로 버튼 인덱스 찾기 ──
Func _HIT_TEST($iMX, $iMY)
For $i = 0 To UBound($g_aBtns) - 1
If $iMX >= $g_aBtns[$i][1] And $iMX <= $g_aBtns[$i][1] + $g_aBtns[$i][3] And _
$iMY >= $g_aBtns[$i][2] And $iMY <= $g_aBtns[$i][2] + $g_aBtns[$i][4] Then
Return $i
EndIf
Next
Return -1
EndFunc
; ── 마우스 이동 ──
Func _WM_MOUSEMOVE($hWnd, $iMsg, $wParam, $lParam)
Local $iMX = BitAND($lParam, 0xFFFF)
Local $iMY = BitShift(BitAND($lParam, 0xFFFF0000), 16)
Local $iIdx = _HIT_TEST($iMX, $iMY)
If $iIdx <> $g_iHoverIdx Then
$g_iHoverIdx = $iIdx
_DRAW_ALL_BUTTONS()
EndIf
Return $GUI_RUNDEFMSG
EndFunc
; ── 마우스 누름 ──
Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
Local $iMX = BitAND($lParam, 0xFFFF)
Local $iMY = BitShift(BitAND($lParam, 0xFFFF0000), 16)
$g_iPressIdx = _HIT_TEST($iMX, $iMY)
If $g_iPressIdx >= 0 Then _DRAW_ALL_BUTTONS()
Return $GUI_RUNDEFMSG
EndFunc
; ── 마우스 뗌 ──
Func _WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
Local $iMX = BitAND($lParam, 0xFFFF)
Local $iMY = BitShift(BitAND($lParam, 0xFFFF0000), 16)
Local $iIdx = _HIT_TEST($iMX, $iMY)
If $iIdx >= 0 And $iIdx = $g_iPressIdx Then
; 버튼 클릭 이벤트
MsgBox(0, "클릭", $g_aBtns[$iIdx][5] & " 버튼 클릭!")
EndIf
$g_iPressIdx = -1
_DRAW_ALL_BUTTONS()
Return $GUI_RUNDEFMSG
EndFunc
세 방식의 차이를 정리하면 다음과 같습니다.
- 방법 1 (BS_FLAT)** — 코드 한 줄이면 되지만 Windows 기본 버튼 렌더링에 의존하므로 완전한 플랫이 아닙니다. 마우스 오버 시 3D 테두리가 나타납니다.
- 방법 2 (Label 활용)** — Label에 배경색과 폰트색을 입히는 방식으로, 코드가 간결하면서도 완전 플랫합니다. 다만 호버/프레스 시 색상 변화를 주려면 타이머나 메시지 처리를 추가해야 합니다.
- 방법 3 (GDI+ Owner-Draw)** — 가장 자유도가 높습니다. 둥근 모서리, 호버 색상 변화, 프레스 효과까지 완전히 커스텀 가능합니다. 코드량이 많지만 SQL*KEY처럼 UI를 세밀하게 제어해야 하는 프로그램에 적합합니다.