#include <ButtonConstants.au3>
#include <Constants.au3>
#include <FontConstants.au3>
#include <GuiButton.au3>
#include <GUIConstantsEx.au3>
#include <GuiReBar.au3>
#include <RebarConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#Region - TimeStamp
; 2013-03-27 11:43:55
#EndRegion - TimeStamp


Opt('MustDeclareVars', 1)
OnAutoItExitRegister('_OnExit')


Global Const $ODA_DRAWENTIRE = 1
Global Const $ODT_BUTTON     = 4

Global $nMsg, $hBrush, $hFont, $Gui, $hBtn1, $hBtn2, $hBtn3, $bt1, $bt2, $bt3, $hReBar
Global $sFont = 'Comic Sans MS', $iHeight = 16, $iWidth = 7, $iWeight = $FW_MEDIUM;$FW_SEMIBOLD;$FW_NORMAL

$Gui = GUICreate("Test")
GUISetBkColor(0xD3DAED)

$hBtn1  = _GUICtrlButton_Create($Gui, 'Button-1', 0, 0, 70, 22, BitOR($BS_OWNERDRAW,$BS_NOTIFY))
$hBtn2  = _GUICtrlButton_Create($Gui, 'Button-2', 0, 0, 70, 22, BitOR($BS_OWNERDRAW,$BS_NOTIFY))
$hBtn3  = _GUICtrlButton_Create($Gui, 'Button-3', 0, 0, 70, 22, BitOR($BS_OWNERDRAW,$BS_NOTIFY))
Global $aBtnInfo[4][5] = [[3], _   ; == [0][0]=Anzahl,  [[Handle-Button, Button-BG-Color, Button-Text-Color(-1=schwarz), Top/Left-Border-Color, Right/Bottom-Border-Color]]
	[$hBtn1, 0x0000FF,       -1, 0xFAF5F2, 0xC0C0C0], _
	[$hBtn2, 0x00FF00, 0xFF0000, 0xFAF5F2, 0xC0C0C0], _
	[$hBtn3, 0xFF0000, 0xFFFFFF, 0xFAF5F2, 0xC0C0C0]]
; == Man kann das Array auch noch erweitern um Font-Informationen einzeln zu jedem Button zu speichern
$bt1 = GUICtrlCreateDummy()
$bt2 = GUICtrlCreateDummy()
$bt3 = GUICtrlCreateDummy()

$hReBar = _GUICtrlRebar_Create($Gui, BitOR($CCS_TOP, $RBS_AUTOSIZE, $RBS_BANDBORDERS))
_GUICtrlRebar_AddBand($hReBar, $hBtn1, 110, 70)
_GUICtrlRebar_AddBand($hReBar, $hBtn2, 110, 70)
_GUICtrlRebar_AddBand($hReBar, $hBtn3, 110, 70)


GUIRegisterMsg($WM_COMMAND,  "WM_COMMAND")
GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
_WinAPI_RedrawWindow($Gui)

GUISetState(@SW_SHOW, $Gui)


While True
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case -3
			Exit
		Case $GUI_EVENT_PRIMARYDOWN, $GUI_EVENT_PRIMARYUP        ; == DOWN- und UP dienen nur zur optischen Darstellung des Buttonklicks
			_Event_PrimaryDownUp($nMsg)
		Case $bt1
			ConsoleWrite('Button-1' & @LF)
		Case $bt2
			ConsoleWrite('Button-2' & @LF)
		Case $bt3
			ConsoleWrite('Button-3' & @LF)
	EndSwitch
WEnd

Func _OnExit()
	_WinAPI_DeleteObject($hBrush)
	_WinAPI_DeleteObject($hFont)
EndFunc

; == Man könnte sich die Dummy-Ctrls sparen und hier in der "WM_COMMAND"-Func die Befehle der Button ausführen.
; == Davon ist aber abzuraten! Die Msg-Routinen sollten schnellstmöglich verlassen werden, deshalb besser ein Dummy befeuern
; == und dieses Event in der Standard-Msg-Auswertung abarbeiten.
Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg
	If BitShift($wParam, 16) <> $BN_CLICKED Then Return $GUI_RUNDEFMSG     ; == nur Click soll ausgewertet werden
	Local $ID
	Switch $lParam         ; == Button-Handle auswerten
		Case $hBtn1
			$ID = $bt1     ; == Dummy-ID zuweisen
		Case $hBtn2
			$ID = $bt2
		Case $hBtn3
			$ID = $bt3
	EndSwitch
	; == Nachricht an gewählte Dummy-ID absetzen
	DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $Gui, "uint", 273, "wparam", $ID, "lparam", 0)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $DRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _
						    "hwnd hItm;hwnd hDC;dword itmRect[4];dword itmData", $lParam)
    If DllStructGetData($DRAWITEMSTRUCT, "cType") <> $ODT_BUTTON Then Return $GUI_RUNDEFMSG         ; == nur OWNERDRAW-Button
	If DllStructGetData($DRAWITEMSTRUCT, "itmAction") <> $ODA_DRAWENTIRE Then Return $GUI_RUNDEFMSG ; == nur Neuzeichnen-Event

	Local $hDC   = DllStructGetData($DRAWITEMSTRUCT, "hDC")
	Local $hItm  = DllStructGetData($DRAWITEMSTRUCT, "hItm")
	Local $sText = _GUICtrlButton_GetText($hItm)                                                    ; == Text des zu zeichnenden Button abfragen
	Local $iColBG, $iColTxt, $iColBorderLT, $iColBorderRB                                           ; == Variablen für Buttonfarben im Array
	_GetBtnColor($hItm, $iColBG, $iColTxt, $iColBorderLT, $iColBorderRB)                            ; == Farben für diesen Button aus Array abfragen
	Local $tRECT = DllStructCreate('int;int;int;int;', DllStructGetPtr($DRAWITEMSTRUCT, "itmRect")) ; == Rect des Button

	_WinAPI_SetBkMode($hDC, $TRANSPARENT)
	$hBrush = _WinAPI_CreateSolidBrush($iColBG)
    Local $hBrushOld = _WinAPI_SelectObject($hDC, $hBrush)
	_WinAPI_FillRect($hDC, DllStructGetPtr($DRAWITEMSTRUCT, "itmRect"), $hBrush)                    ; == Button-Hintergrundfarbe zeichnen
	Local $iColOld = _WinAPI_SetTextColor($hDC, $iColTxt)                                           ; == Textfarbe anwählen

	; == Infos für Font könnten auch einzeln für jeden Button im Array hinterlegt werden
	Local $nHeight = $iHeight, $nWidth = $iWidth, $nEscape = 0, $nOrientn = 0, $fnWeight = $iWeight, $bItalic = False, $bUnderline = False
	Local $bStrikeout = False, $nCharset = $DEFAULT_CHARSET, $nOutputPrec = $OUT_DEFAULT_PRECIS, $nClipPrec = $CLIP_DEFAULT_PRECIS
	Local $nQuality = $DEFAULT_QUALITY, $nPitch = 0, $szFace = $sFont
	$hFont = _WinAPI_CreateFont($nHeight, $nWidth, $nEscape, $nOrientn, $fnWeight, $bItalic, $bUnderline, _
                                $bStrikeout, $nCharset, $nOutputPrec, $nClipPrec, $nQuality, $nPitch, $szFace)
	Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)

	_WinAPI_DrawText($hDC, $sText, $tRECT, BitOR($DT_CENTER,$DT_VCENTER,$DT_SINGLELINE))            ; == Button-Text schreiben
	_WinAPI_SetTextColor($hDC, $iColOld)                                                            ; == Textfarbe zurücksetzen
	_WinAPI_DrawButtonRect($hDC, $tRECT, $iColBorderLT, $iColBorderRB, 1)                           ; == Button-Ränder zeichnen (Left u. Top hell / Right u. Bottom dunkel)
    _WinAPI_SelectObject($hDC, $hBrushOld)
	_WinAPI_SelectObject($hDC, $hOldFont)

    Return $GUI_RUNDEFMSG
EndFunc  ;==>WM_DRAWITEM

Func _Event_PrimaryDownUp($_iEVENT)
	Local $oldMode = Opt('MouseCoordMode', 2), $aMouse = MouseGetPos(), $iColBorderRB
	Opt('MouseCoordMode', $oldMode)
	Local $hWndBtn = _GetBtnHwndFromMouse($aMouse[0], $aMouse[1], $iColBorderRB)
	If $hWndBtn = 0 Then Return
	Local $aCtrlPos = ControlGetPos($Gui, '', _WinAPI_GetDlgCtrlID($hWndBtn))                       ; == Pos. im Rebar ist variabel, daher immer neu abfragen
	Local Static $DC = _WinAPI_GetDC($Gui)
	Switch $_iEVENT
		Case $GUI_EVENT_PRIMARYUP
			_WinAPI_ReleaseDC($Gui, $DC)
		Case $GUI_EVENT_PRIMARYDOWN
			Local $hPenLT = _WinAPI_CreatePen($PS_SOLID, 1, $iColBorderRB)                          ; == Farbe von Right/Bottom verwenden
			_WinAPI_SelectObject($DC, $hPenLT)
			_WinAPI_DrawLine($DC, $aCtrlPos[0], $aCtrlPos[1], $aCtrlPos[0], $aCtrlPos[1]+$aCtrlPos[3]-1)    ; == Left
			_WinAPI_DrawLine($DC, $aCtrlPos[0], $aCtrlPos[1], $aCtrlPos[0]+$aCtrlPos[2], $aCtrlPos[1])      ; == Top
			_WinAPI_DeleteObject($hPenLT)
	EndSwitch
EndFunc  ;==>_Event_PrimaryDownUp

Func _GetBtnColor($_hWnd, ByRef $_iColBG, ByRef $_iColTxt, ByRef $_iColBorderLT, ByRef $_iColBorderRB)
	For $i = 1 To $aBtnInfo[0][0]
		If $aBtnInfo[$i][0] = $_hWnd Then
			$_iColBG =       $aBtnInfo[$i][1]
			If $aBtnInfo[$i][2] = -1 Then $aBtnInfo[$i][2] = 0x000000
			$_iColTxt =      $aBtnInfo[$i][2]
			$_iColBorderLT = $aBtnInfo[$i][3]
			$_iColBorderRB = $aBtnInfo[$i][4]
			Return
		EndIf
	Next
EndFunc  ;==>_GetBtnColor

Func _GetBtnHwndFromMouse($_iX, $_iY, ByRef $_iColBorderRB)
	Local $aCtrl
	For $i = 1 To $aBtnInfo[0][0]
		$aCtrl = ControlGetPos($Gui, '', _WinAPI_GetDlgCtrlID($aBtnInfo[$i][0]))
		If ($aCtrl[0] <= $_iX And $_iX <= $aCtrl[2]+$aCtrl[0]) And ($aCtrl[1] <= $_iY And $_iY <= $aCtrl[3]+$aCtrl[1]) Then
			$_iColBorderRB = $aBtnInfo[$i][4]
			Return $aBtnInfo[$i][0]
		EndIf
	Next
	Return 0
EndFunc  ;==>_GetBtnHwndFromMouse

Func _WinAPI_DrawButtonRect(ByRef $_hDC, $_tpRECT, $_iPenColorLT, $_iPenColorRB, $_iPenSize=1)
	Local $tRECT
	If IsDllStruct($_tpRECT) Then
		$tRECT = $_tpRECT
	ElseIf IsPtr($_tpRECT) Then
		$tRECT = DllStructCreate('int;int;int;int;', $_tpRECT)
	EndIf
	Local $hPenLT = _WinAPI_CreatePen($PS_SOLID, $_iPenSize, $_iPenColorLT)
	Local $hPenRB = _WinAPI_CreatePen($PS_SOLID, $_iPenSize, $_iPenColorRB)
	Local $left = DllStructGetData($tRECT, 1), $top = DllStructGetData($tRECT, 2), $right = DllStructGetData($tRECT, 3), $bottom = DllStructGetData($tRECT, 4)
	_WinAPI_SelectObject($_hDC, $hPenLT)
	_WinAPI_DrawLine($_hDC, $left, $top, $left, $bottom-$_iPenSize)   ; == Left
	_WinAPI_DrawLine($_hDC, $left, $top, $right, $top)                ; == Top
	_WinAPI_SelectObject($_hDC, $hPenRB)
	_WinAPI_DrawLine($_hDC, $right-$_iPenSize, $top, $right-$_iPenSize, $bottom-$_iPenSize)   ; == Right
	_WinAPI_DrawLine($_hDC, $left, $bottom-$_iPenSize, $right-$_iPenSize, $bottom-$_iPenSize) ; == Bottom
	_WinAPI_DeleteObject($hPenLT)
	_WinAPI_DeleteObject($hPenRB)
EndFunc  ;==>_WinAPI_DrawButtonRect