문서 편집 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다: 사용자.
== 플랫 버튼 스타일 == ## 1. BS_FLAT 스타일 (가장 간단) <source lang=autoit> #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 </source> 3D 테두리가 제거되지만, 마우스 오버 시 테두리가 살아나서 완전한 플랫은 아닙니다. ## 2. Label + 색상 조합 (완전 플랫) <source lang=autoit> #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 </source> ## 3. GDI+ Owner-Draw (호버 효과 포함) <source lang=autoit> #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 </source> 세 방식의 차이를 정리하면 다음과 같습니다. **방법 1 (BS_FLAT)** — 코드 한 줄이면 되지만 Windows 기본 버튼 렌더링에 의존하므로 완전한 플랫이 아닙니다. 마우스 오버 시 3D 테두리가 나타납니다. **방법 2 (Label 활용)** — Label에 배경색과 폰트색을 입히는 방식으로, 코드가 간결하면서도 완전 플랫합니다. 다만 호버/프레스 시 색상 변화를 주려면 타이머나 메시지 처리를 추가해야 합니다. **방법 3 (GDI+ Owner-Draw)** — 가장 자유도가 높습니다. 둥근 모서리, 호버 색상 변화, 프레스 효과까지 완전히 커스텀 가능합니다. 코드량이 많지만 SQL*KEY처럼 UI를 세밀하게 제어해야 하는 프로그램에 적합합니다. === 플랫한 버튼 스타일 예제 === <source lang=autoit> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <WinAPI.au3> ; ── Tab Control 스타일 상수 ── Global Const $TCS_MULTILINE = 0x0200 Global Const $TCS_BUTTONS = 0x0100 Global Const $TCS_FLATBUTTONS = 0x0008 Global Const $TCS_OWNERDRAWFIXED = 0x2000 Global Const $ODT_TAB = 101 Global Const $ODS_SELECTED = 0x0001 ; ── 색상 설정 ── Global Const $CLR_TAB_SELECTED_BG = 0x2196F3 ; 선택된 탭 배경 (파란색) Global Const $CLR_TAB_SELECTED_TEXT = 0xFFFFFF ; 선택된 탭 텍스트 (흰색) Global Const $CLR_TAB_NORMAL_BG = 0xE0E0E0 ; 일반 탭 배경 (밝은 회색) Global Const $CLR_TAB_NORMAL_TEXT = 0x333333 ; 일반 탭 텍스트 (진한 회색) Global Const $CLR_TAB_HOVER_BG = 0xBBDEFB ; 호버 탭 배경 (연한 파란색) Global Const $CLR_TAB_HOVER_TEXT = 0x1565C0 ; 호버 탭 텍스트 Global Const $CLR_GUI_BG = 0xFAFAFA ; GUI 배경 Global Const $CLR_CONTENT_BG = 0xFFFFFF ; 탭 콘텐츠 영역 배경 ; ── 폰트 설정 ── Global Const $TAB_FONT_NAME = "맑은 고딕" Global Const $TAB_FONT_SIZE = 10 ; ── 탭 데이터 ── Global $g_aTabNames[] = [ _ "환경설정", "단축키 관리", "실행파일", "후킹설정", _ "Direct Key", "매크로", "히스토리", "도움말" _ ] Global $g_hGUI, $g_hTab Global $g_aTabItems[UBound($g_aTabNames)] Global $g_aTabLabels[UBound($g_aTabNames)] ; 탭별 콘텐츠 라벨 Global $g_iHoverTab = -1 ; ── GUI 생성 ── $g_hGUI = GUICreate("SQL*KEY - Flat Tab Demo", 700, 500) GUISetBkColor($CLR_GUI_BG) GUISetFont($TAB_FONT_SIZE, 400, 0, $TAB_FONT_NAME) ; ── Tab 컨트롤 생성 ── ; TCS_OWNERDRAWFIXED: 직접 그리기 ; TCS_BUTTONS: 버튼 스타일 ; TCS_MULTILINE: 다중 행 ; TCS_FLATBUTTONS: 플랫 버튼 (owner-draw와 함께 사용) $g_hTab = GUICtrlCreateTab(10, 10, 680, 480, _ BitOR($TCS_OWNERDRAWFIXED, $TCS_BUTTONS, $TCS_MULTILINE, $TCS_FLATBUTTONS)) GUICtrlSetFont($g_hTab, $TAB_FONT_SIZE, 400, 0, $TAB_FONT_NAME) ; ── TabItem 생성 ── For $i = 0 To UBound($g_aTabNames) - 1 $g_aTabItems[$i] = GUICtrlCreateTabItem($g_aTabNames[$i]) ; 각 탭의 콘텐츠 예시 $g_aTabLabels[$i] = GUICtrlCreateLabel( _ "[ " & $g_aTabNames[$i] & " ] 탭 콘텐츠 영역", _ 30, 80, 640, 380) GUICtrlSetFont($g_aTabLabels[$i], 14, 400, 0, $TAB_FONT_NAME) GUICtrlSetColor($g_aTabLabels[$i], 0x757575) GUICtrlSetBkColor($g_aTabLabels[$i], $CLR_CONTENT_BG) Next GUICtrlCreateTabItem("") ; 탭 아이템 종료 ; ── WM_DRAWITEM 등록 (탭 커스텀 그리기) ── GUIRegisterMsg($WM_DRAWITEM, "_WM_DRAWITEM") ; ── WM_MOUSEMOVE 등록 (호버 효과) ── GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") GUISetState(@SW_SHOW) ; ── 메인 루프 ── While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd ; ══════════════════════════════════════════════════════ ; WM_DRAWITEM 핸들러 - 탭을 플랫 스타일로 직접 그리기 ; ══════════════════════════════════════════════════════ Func _WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam) ; DRAWITEMSTRUCT 구조체 파싱 Local $tDRAWITEM = DllStructCreate( _ "uint CtlType;" & _ "uint CtlID;" & _ "uint itemID;" & _ "uint itemAction;" & _ "uint itemState;" & _ "hwnd hwndItem;" & _ "handle hDC;" & _ "long rcLeft;long rcTop;long rcRight;long rcBottom;" & _ "ulong_ptr itemData", _ $lParam) Local $iCtlType = DllStructGetData($tDRAWITEM, "CtlType") If $iCtlType <> $ODT_TAB Then Return $GUI_RUNDEFMSG Local $iItemID = DllStructGetData($tDRAWITEM, "itemID") Local $iState = DllStructGetData($tDRAWITEM, "itemState") Local $hDC = DllStructGetData($tDRAWITEM, "hDC") Local $iLeft = DllStructGetData($tDRAWITEM, "rcLeft") Local $iTop = DllStructGetData($tDRAWITEM, "rcTop") Local $iRight = DllStructGetData($tDRAWITEM, "rcRight") Local $iBottom = DllStructGetData($tDRAWITEM, "rcBottom") Local $bSelected = BitAND($iState, $ODS_SELECTED) ; ── 색상 결정 ── Local $iBgColor, $iTextColor If $bSelected Then $iBgColor = $CLR_TAB_SELECTED_BG $iTextColor = $CLR_TAB_SELECTED_TEXT ElseIf $iItemID = $g_iHoverTab Then $iBgColor = $CLR_TAB_HOVER_BG $iTextColor = $CLR_TAB_HOVER_TEXT Else $iBgColor = $CLR_TAB_NORMAL_BG $iTextColor = $CLR_TAB_NORMAL_TEXT EndIf ; ── 배경 채우기 (1px 간격으로 버튼 분리) ── Local $tRect = DllStructCreate("long Left;long Top;long Right;long Bottom") DllStructSetData($tRect, "Left", $iLeft + 1) DllStructSetData($tRect, "Top", $iTop + 1) DllStructSetData($tRect, "Right", $iRight - 1) DllStructSetData($tRect, "Bottom", $iBottom - 1) Local $hBrush = _WinAPI_CreateSolidBrush($iBgColor) _WinAPI_FillRect($hDC, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) ; ── 선택된 탭 하단 액센트 라인 ── If $bSelected Then Local $tAccent = DllStructCreate("long Left;long Top;long Right;long Bottom") DllStructSetData($tAccent, "Left", $iLeft + 1) DllStructSetData($tAccent, "Top", $iBottom - 4) DllStructSetData($tAccent, "Right", $iRight - 1) DllStructSetData($tAccent, "Bottom", $iBottom - 1) Local $hAccentBrush = _WinAPI_CreateSolidBrush(0x0D47A1) ; 진한 파란 액센트 _WinAPI_FillRect($hDC, $tAccent, $hAccentBrush) _WinAPI_DeleteObject($hAccentBrush) EndIf ; ── 텍스트 그리기 ── Local $sText = "" If $iItemID >= 0 And $iItemID < UBound($g_aTabNames) Then $sText = $g_aTabNames[$iItemID] EndIf ; 폰트 생성 Local $hFont = _WinAPI_CreateFont($TAB_FONT_SIZE + 3, 0, 0, 0, _ ($bSelected ? 700 : 400), _ ; 선택 시 Bold False, False, False, _ $DEFAULT_CHARSET, 0, 0, 5, 0, $TAB_FONT_NAME) Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) ; 텍스트 색상 및 배경 모드 DllCall("gdi32.dll", "int", "SetBkMode", "handle", $hDC, "int", 1) ; TRANSPARENT DllCall("gdi32.dll", "int", "SetTextColor", "handle", $hDC, _ "int", $iTextColor) ; 텍스트 중앙 정렬 출력 Local $tTextRect = DllStructCreate("long Left;long Top;long Right;long Bottom") DllStructSetData($tTextRect, "Left", $iLeft) DllStructSetData($tTextRect, "Top", $iTop) DllStructSetData($tTextRect, "Right", $iRight) DllStructSetData($tTextRect, "Bottom", $iBottom) ; DT_CENTER=1, DT_VCENTER=4, DT_SINGLELINE=32 DllCall("user32.dll", "int", "DrawTextW", _ "handle", $hDC, _ "wstr", $sText, _ "int", -1, _ "struct*", $tTextRect, _ "uint", BitOR(1, 4, 32)) _WinAPI_SelectObject($hDC, $hOldFont) _WinAPI_DeleteObject($hFont) Return True ; 그리기 처리 완료 EndFunc ; ══════════════════════════════════════════════════════ ; WM_NOTIFY 핸들러 - 호버 효과를 위한 마우스 추적 ; ══════════════════════════════════════════════════════ Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate("hwnd hWndFrom;uint_ptr IDFrom;int Code", $lParam) Local $iCode = DllStructGetData($tNMHDR, "Code") ; TCN_SELCHANGE = -551 (탭 변경 시 강제 다시 그리기) If $iCode = -551 Then _WinAPI_InvalidateRect(GUICtrlGetHandle($g_hTab)) EndIf Return $GUI_RUNDEFMSG EndFunc ; ══════════════════════════════════════════════════════ ; WinAPI 보조 함수 ; ══════════════════════════════════════════════════════ Func _WinAPI_CreateSolidBrush($iColor) Local $aRet = DllCall("gdi32.dll", "handle", "CreateSolidBrush", "int", $iColor) Return $aRet[0] EndFunc Func _WinAPI_FillRect($hDC, $tRect, $hBrush) DllCall("user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", $hBrush) EndFunc </source> [[category:autoit]]
문서 저장 미리 보기 차이 보기 취소