In the _SB_Paint function we make the task of painting our SimpleButton control a bit easier for ourselves by separating the main tasks into other sub-functions: _SB_PaintBackground, _SB_PaintText and _SB_PaintBorder. We create a double buffer beforehand and BitBlt after the calls to the other _SB_Paint sub-functions.
_SB_Paint and the other sub-functions make use of our both our internal and external variables (with calls to the internal helper functions: __GetIntProperty, __GetExtProperty) to detect states (selected/not selected), mouse over (or not) and to control styles, colors, fonts and other attributes used in our SimpleButton control.
The sub functions typically are passed some internal variables as parameters, for example:
With all these attributes the end-user will have control our how the SimpleButton will look depending on the default properties set and any additional ones the end-user sets themselves.
Each of the sub-functions will read a particular external property depending on the status of the internal properties, so in our _SB_PaintBackground function, depending on whether the mouse is over the control or not it will fetch a different external property.
Here is the complete _SB_PaintBackground function to illustrate this:
;-------------------------------------------------------------------------------------
; _SB_PaintBackground - Paints the background of the SimpleButton control
;-------------------------------------------------------------------------------------
_SB_PaintBackground PROC PRIVATE hControl:DWORD, hdc:DWORD, lpRect:DWORD, /
bEnabledState:DWORD, bMouseOver:DWORD, /
bSelectedState:DWORD
LOCAL BackColor:DWORD
LOCAL hBrush:DWORD
LOCAL hOldBrush:DWORD
.IF bEnabledState == TRUE
.IF bSelectedState == FALSE
.IF bMouseOver == FALSE
Invoke __GetExtProperty, hControl, @SimpleButtonBackColor
.ELSE
Invoke __GetExtProperty, hControl, @SimpleButtonBackColorAlt
.ENDIF
.ELSE
.IF bMouseOver == FALSE
Invoke __GetExtProperty, hControl, @SimpleButtonBackColorSel
.ELSE
Invoke __GetExtProperty, hControl, @SimpleButtonBackColorSelAlt
.ENDIF
.ENDIF
.ELSE
Invoke __GetExtProperty, hControl, @SimpleButtonBackColorDisabled
.ENDIF
.IF eax == 0 ; try to get default back color if others are set to 0
Invoke __GetExtProperty, hControl, @SimpleButtonBackColor
.ENDIF
mov BackColor, eax
Invoke GetStockObject, DC_BRUSH
mov hBrush, eax
Invoke SelectObject, hdc, eax
mov hOldBrush, eax
Invoke SetDCBrushColor, hdc, BackColor
Invoke FillRect, hdc, lpRect, hBrush
.IF hOldBrush != 0
Invoke SelectObject, hdc, hOldBrush
Invoke DeleteObject, hOldBrush
.ENDIF
.IF hBrush != 0
Invoke DeleteObject, hBrush
.ENDIF
ret
_SB_PaintBackground ENDP
So if bEnabled is TRUE and the SimpleButton control's selected state (bSelectedState) is FALSE we just have to determine if the mouse is over the control or not.
We then clean up the brushes used, and return to _SB_Paint ready to call the next sub-function to handle painting our text and border. Each of those sub-functions works in a similar manner, by fetching the appropriate external property value and then painting based on those values for text or border colors, depending on the status of the control: selected, enabled or if the mouse is over the control.
If the mouse is not over the control we fetch the default @SimpleButtonBackColor property which is a DWORD value to paint the background with. If however the mouse is over the control we fetch the @SimpleButtonBackColorAlt property which is another DWORD value (which may be the same value or a different value than the @SimpleButtonBackColor property). Similarly we can fetch colors for when our control is disabled or if is selected state has been set with our SimpleButtonSetState function, or if the state of our control has changed automatically as a result of specifying the SBBS_AUTOSTATE flag when created the control (which allows us to toggle the state of our SimpleButton control when it is clicked each time)
Then we proceed to paint the background of our SimpleButton control with the color retrieved, using the standard api call.