02.10.2025, 02:28 AM
OwnerDrawn means one has to draw both button text, border and colors self. It's the only way to change button colors, so it can be useful in some cases. One usually don't use %DT_NOPREFIX there, but it can be done using something like the code below:
Code:
'====================================================================
' Simple ownerdrawn button code
'====================================================================
#COMPILE EXE
#DIM ALL
%UNICODE = 1
#INCLUDE "WIN32API.INC"
'====================================================================
FUNCTION PBMAIN
LOCAL hDlg AS LONG
DIALOG NEW 0 ,"Button test", , , 110, 45, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
DIALOG SET COLOR hDlg, -1, %LTGRAY
'------------------------------------------------------------------
' create one standard button and one ownerdrawn, to see difference
CONTROL ADD BUTTON, hDlg, %IDOK, "Standard X&Y", 5, 5, 100, 15, %WS_TABSTOP
CONTROL ADD BUTTON, hDlg, %IDCANCEL, "DT_Noprefix X&Y", 5, 25, 100, 15, %BS_OWNERDRAW OR %WS_TABSTOP
'------------------------------------------------------------------
DIALOG SHOW MODELESS hDlg, CALL DlgProc
DO
DIALOG DOEVENTS
LOOP WHILE ISWIN(hDlg)
END FUNCTION
'====================================================================
CALLBACK FUNCTION DlgProc
SELECT CASE CB.MSG
CASE %WM_INITDIALOG
CASE %WM_COMMAND
IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
SELECT CASE CB.CTL
CASE %IDOK : ' do whatever
CASE %IDCANCEL : ' do something else
END SELECT
END IF
CASE %WM_DRAWITEM 'time to draw ownerdrawn button
IF CB.WPARAM = %IDCANCEL THEN
' for system colors, set bgColor to GetSysColor(%COLOR_BTNFACE)
' and set txtColor to GetSysColor(%COLOR_BTNTEXT)
' dwStyle set DrawText style - here centered and no prefix handling of &
' without %DT_NOPREFIX, character after & will be underlined, just like standard button
LOCAL dwStyle AS DWORD
dwStyle = %DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER OR %DT_NOPREFIX
DrawButton GetDlgItem(CB.HNDL, %IDCANCEL), CB.LPARAM, dwStyle, RGB(255, 204, 0), %RED
END IF
END SELECT
END FUNCTION
'====================================================================
' draw ownerdrawn button
'--------------------------------------------------------------------
SUB DrawButton (hButton AS LONG, lParam AS LONG, dwStyle AS LONG, bgColor AS LONG, txtColor AS LONG)
LOCAL hBrush AS DWORD, lpDis AS DRAWITEMSTRUCT PTR, wzTxt AS WSTRINGZ * 100
lpDis = lParam
hBrush = CreateSolidBrush(bgColor) 'create brush
SetBkColor @lpDis.hDC, bgColor 'text background color
SetTextColor @lpDis.hDC, txtColor 'text color
GetWindowText hButton, wzTxt, SIZEOF(wzTxt) 'grab text
IF (@lpDis.itemState AND %ODS_SELECTED) THEN ' pressed button
DrawFrameControl @lpDis.hDC, @lpDis.rcItem, %DFC_BUTTON, %DFCS_BUTTONPUSH OR %DFCS_PUSHED
OffsetRect @lpDis.rcItem, 1, 1 ' move text rect some
ELSE
DrawFrameControl @lpDis.hDC, @lpDis.rcItem, %DFC_BUTTON, %DFCS_BUTTONPUSH
END IF
InflateRect @lpDis.RcItem, -2, -2 'smaller rect to avoid FillRect paint over borders
FillRect @lpDis.hDc, @lpDis.rcItem, hBrush 'fill surface, then draw text
@lpDis.RcItem.nTop -= 2 'adjust text rect a little
DrawText @lpDis.hDC, wzTxt, -1, @lpDis.rcItem, dwStyle
@lpDis.RcItem.nTop += 2 'restore rect
IF (@lpDis.itemState AND %ODS_FOCUS) THEN 'if button has focus
SetTextColor @lpDis.hDC, GetSysColor(%COLOR_BTNTEXT) 'reset text color for focus rect
InflateRect @lpDis.RcItem, -1, -1 'adjust focus rect some
DrawFocusRect @lpDis.hDC, @lpDis.rcItem
END IF
DeleteObject hBrush ' delete what we created
END SUB