#Region - TimeStamp
; 2013-03-26 15:14:28
#EndRegion - TimeStamp

#include <ButtonConstants.au3>
#include <FontConstants.au3>
#include <GuiButton.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Opt('MustDeclareVars', 1)
OnAutoItExitRegister('_OnExit')


Global Const $ODA_DRAWENTIRE = 1
Global Const $ODT_BUTTON     = 4

Global $hBrush, $hFont, $Gui, $hBtn1, $hBtn2, $bt1, $bt2
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', 20, 20, 70, 22, BitOR($BS_OWNERDRAW,$BS_NOTIFY))
$hBtn2 = _GUICtrlButton_Create($Gui, 'Button-2', 20, 50, 70, 22, BitOR($BS_OWNERDRAW,$BS_NOTIFY))
Global $aBtnInfo[3][6] = [[2], _   ; == [0][0]=Anzahl,  [[Handle-Button, Button-BG-Color, Button-Text-Color(-1=schwarz), Top/Left-Border-Color, Right/Bottom-Border-Color, ArrayPos(rel. in Client)]]
	[$hBtn1, 0x00FFFF, 0xFF0000, 0xFAF5F2, 0xC0C0C0, ControlGetPos($Gui, '', _WinAPI_GetDlgCtrlID($hBtn1))], _
	[$hBtn2, 0xFF00FF, -1,       0xFAF5F2, 0xC0C0C0, ControlGetPos($Gui, '', _WinAPI_GetDlgCtrlID($hBtn2))]]
; == Man kann das Array auch noch erweitern um Font-Informationen einzeln zu jedem Button zu speichern

$bt1 = GUICtrlCreateDummy()
$bt2 = GUICtrlCreateDummy()


GUIRegisterMsg($WM_COMMAND,  "WM_COMMAND")
GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
_WinAPI_RedrawWindow($Gui)

GUISetState(@SW_SHOW, $Gui)


While True
	Switch GUIGetMsg()
		Case -3
			Exit
		Case $GUI_EVENT_PRIMARYDOWN              ; == DOWN- und UP dienen nur zur optischen Darstellung des Buttonklicks
			_Event_PrimaryDownUp(1)
		Case $GUI_EVENT_PRIMARYUP
			_Event_PrimaryDownUp(0)
		Case $bt1
			ConsoleWrite('Button-1' & @LF)
		Case $bt2
			ConsoleWrite('Button-2' & @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
	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, $iIndex                                  ; == Variablen für Buttonfarben u. Index im Array
	_GetBtnColor($hItm, $iColBG, $iColTxt, $iColBorderLT, $iColBorderRB, $iIndex)                   ; == 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($_iDown)
	Local $oldMode = Opt('MouseCoordMode', 2), $aSize[4], $aMouse = MouseGetPos()
	Local $hWndBtn = _GetBtnHwndFromMouse($aMouse[0], $aMouse[1], $aSize)
	Opt('MouseCoordMode', $oldMode)
	If $hWndBtn = 0 Then Return
	Switch $_iDown
		Case 0
			ControlMove($Gui, '', _WinAPI_GetDlgCtrlID($hWndBtn), $aSize[0]-1, $aSize[1]-1)
		Case 1
			ControlMove($Gui, '', _WinAPI_GetDlgCtrlID($hWndBtn), $aSize[0]+1, $aSize[1]+1)
	EndSwitch
EndFunc  ;==>_Event_PrimaryDownUp

Func _GetBtnColor($_hWnd, ByRef $_iColBG, ByRef $_iColTxt, ByRef $_iColBorderLT, ByRef $_iColBorderRB, ByRef $_iIndex)
	For $i = 1 To $aBtnInfo[0][0]
		If $aBtnInfo[$i][0] = $_hWnd Then
			$_iColBG =       $aBtnInfo[$i][1]
			$_iColTxt =      $aBtnInfo[$i][2]
			If $aBtnInfo[$i][2] = -1 Then $aBtnInfo[$i][2] = 0x000000
			$_iColBorderLT = $aBtnInfo[$i][3]
			$_iColBorderRB = $aBtnInfo[$i][4]
			$_iIndex       = $aBtnInfo[$i][5]
			Return
		EndIf
	Next
EndFunc  ;==>_GetBtnColor

Func _GetBtnHwndFromMouse($_iX, $_iY, ByRef $_aSize)
	Local $aCtrl
	For $i = 1 To $aBtnInfo[0][0]
		$aCtrl = $aBtnInfo[$i][5]
		If ($aCtrl[0] <= $_iX And $_iX <= $aCtrl[2]+$aCtrl[0]) And ($aCtrl[1] <= $_iY And $_iY <= $aCtrl[3]+$aCtrl[1]) Then
			$_aSize = $aCtrl
			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