Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Getting the Enter Key to click an ownerdrawn button that has focus...

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting the Enter Key to click an ownerdrawn button that has focus...

    I can't take credit for coming up with this on my own, all I did was find posts I believe from Borje and Semen that helped me learn how to do ownerdrawn buttons, and from Dominic on how to fool windows into thinking what button was actually the default button, and put those together.

    So here it is, if anyone's interested:

    Code:
    #PBFORMS Created
    '--------------------------------------------------------------------------------
    ' The first line in this file is a PBForms metastatement.
    ' It should ALWAYS be the first line of the file. Other
    ' PBForms metastatements are placed at the beginning and
    ' ending of blocks of code that should be edited using
    ' PBForms only. Do not edit or delete these
    ' metastatements or PBForms will not be able to reread
    ' the file correctly. See the PBForms documentation for
    ' more information.
    ' Beginning blocks begin like this: #PBForms Begin ...
    ' Ending blocks begin like this:    #PBForms End ...
    ' Other PBForms metastatements such as:
    '     #PBForms Declarations
    ' are used to tell PBForms where to insert additional
    ' code. Feel free to make changes anywhere else in the file.
    '--------------------------------------------------------------------------------
    
    #COMPILE EXE
    #DIM ALL
    
    '--------------------------------------------------------------------------------
    '   ** Includes **
    '--------------------------------------------------------------------------------
    #PBFORMS Begin Includes
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #PBFORMS End Includes
    '--------------------------------------------------------------------------------
    
    #INCLUDE "COMDLG32.INC"
    
    '--------------------------------------------------------------------------------
    '   ** Constants **
    '--------------------------------------------------------------------------------
    #PBFORMS Begin Constants
    %IDD_DIALOG1    = 101
    %IDC_BUTTON1    = 1001
    %IDC_BUTTON2    = 1002
    %IDC_BUTTON3    = 1003
    %IDC_BUTTON4    = 1004
    %IDC_BUTTON5    = 1005
    %IDC_BUTTON6    = 1006
    %IDC_BUTTON7    = 1007
    %IDC_BUTTON8    = 1008
    %IDC_BUTTON9    = 1009
    %IDC_TEXTBOX1   = 1010
    %IDC_CHECKBOX1  = 1011
    %IDC_OPTION1    = 1012
    %IDC_COMBOBOX1  = 1013
    #PBFORMS End Constants
    '--------------------------------------------------------------------------------
    
    '--------------------------------------------------------------------------------
    '   ** Declarations **
    '--------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION SampleComboBox(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL _
        lCount AS LONG) AS LONG
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS Declarations
    '--------------------------------------------------------------------------------
    
    GLOBAL MainProc         AS LONG     'Used for subclassing
    GLOBAL DefButton        AS LONG     'Used to fool Windows into thinking what button is default
    GLOBAL forcol           AS DWORD    'Foreground Color
    GLOBAL bakcol           AS DWORD    'Background Color
    
    '--------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        'Start with White Text and Blue Background
        forcol=%WHITE
        bakcol=%BLUE
    
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '--------------------------------------------------------------------------------
    
    '--------------------------------------------------------------------------------
    '   ** CallBacks **
    '--------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
    
        STATIC cxb      AS LONG
        STATIC cyb      AS LONG
        STATIC cxi      AS LONG
        STATIC cyi      AS LONG
        STATIC hBrush1  AS LONG
        STATIC hBrush2  AS LONG
    
        LOCAL lRet      AS LONG
        LOCAL lb        AS LOGBRUSH
        LOCAL lb2       AS LOGBRUSH
        LOCAL tDrawItem AS DRAWITEMSTRUCT PTR
        LOCAL lpcc      AS ChooseColorAPI
        LOCAL result    AS LONG
        LOCAL x         AS LONG
        LOCAL tRect     AS Rect
        LOCAL ry        AS LONG
        LOCAL DispText  AS STRING
        LOCAL DispStr   AS ASCIIZ*%MAX_PATH
    
        DIM lpCustColor(15) AS STATIC LONG
    
        SELECT CASE CBMSG
            CASE %WM_INITDIALOG
                'Create Brush for background color
                lb.lbStyle=%BS_SOLID
                lb.lbColor=bakcol
                hBrush1=CreateBrushIndirect(lb)
                'Create Brush for default rectangle
                lb2.lbStyle=%BS_SOLID
                lb2.lbColor=%BLACK
                hBrush2=CreateBrushIndirect(lb2)
                'Stuff used for drawing code
                cxb = GetSystemMetrics(%SM_CXBORDER): cyb = GetSystemMetrics(%SM_CYBORDER)
                cxi = GetSystemMetrics(%SM_CXSMICON): cyi = GetSystemMetrics(%SM_CYSMICON)
                'Subclass all ownerdrawn command buttons
                MainProc = GetWindowLong(GetDlgItem(CBHNDL,%IDC_BUTTON1), %GWL_WNDPROC)
                FOR x=%IDC_BUTTON1 TO %IDC_BUTTON9
                    lRet=SetWindowLong(GetDlgItem(CBHNDL,x), %GWL_WNDPROC, CODEPTR(ButtonSubClassProc))
                NEXT
                'Prefill custom colors just in case you change them while the program is running
                FOR result=0 TO 15
                    lpCustColor(result)=RGB(255,255,255)
                NEXT
            CASE %WM_DESTROY
                'Remove subclassing
                FOR x=%IDC_BUTTON1 TO %IDC_BUTTON9
                    SetWindowLong GetDlgItem(CBHNDL, x), %GWL_WNDPROC, MainProc
                NEXT
                'Clean Up
                DeleteObject hBrush1
                DeleteObject hBrush2
            CASE %WM_DRAWITEM
                tDrawItem = CBLPARAM
                SELECT CASE @tDrawItem.CtlID
                    CASE %IDC_BUTTON1 TO %IDC_BUTTON9
                        tRect = @tDrawItem.RcItem: ry = tRect.nBottom
                        FrameRect @tDrawItem.hDc,@tDrawItem.rcItem, GetStockObject(%BLACK_BRUSH)
                        FillRect @tDrawItem.hDc, @tDrawItem.rcItem, hBrush1
                        IF(@tDrawItem.itemState AND %ODS_SELECTED) THEN
                            DrawEdge @tDrawItem.hDC, @tDrawItem.rcItem, %Edge_Sunken, %BF_RECT
                        ELSE
                            DrawEdge @tDrawItem.hDC, @tDrawItem.rcItem, %Edge_Raised, %BF_RECT
                        END IF
                        SetBkMode @tDrawItem.hDC, %TRANSPARENT
                        SetTextColor @tDrawItem.hDC, forcol
                        CONTROL GET TEXT CBHNDL, @tDrawItem.CtlID TO DispText
                        DispStr=DispText
                        DrawText @tDrawItem.hDC, DispStr, -1, tRect, %DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER
                        IF (@tDrawItem.itemState AND %ODS_FOCUS) THEN
                            FrameRect @tDrawItem.hDC, @tDrawItem.rcItem, hBrush2
                            InflateRect @tDrawItem.rcItem, -cxb, -cyb
                            IF(@tDrawItem.itemState AND %ODS_SELECTED) THEN
                                DrawEdge @tDrawItem.hDC, @tDrawItem.rcItem, %Edge_Sunken, %BF_RECT
                            ELSE
                                DrawEdge @tDrawItem.hDC, @tDrawItem.rcItem, %Edge_Raised, %BF_RECT
                            END IF
                            InflateRect @tDrawItem.RcItem, -3 * cxb, -3 * cyb
                            DrawFocusRect @tDrawItem.hDC, @tDrawItem.rcItem
                        END IF
                        FUNCTION = %False
                END SELECT
            CASE %DM_GETDEFID
                'If an ownerdrawn button has focus, tell Windows it's the default button
                IF DefButton>0 THEN FUNCTION=MAKLNG(GetDlgCtrlID(DefButton), %DC_HASDEFID)
            CASE %WM_COMMAND
                SELECT CASE CBCTL
                    CASE %IDCANCEL
                        DIALOG END CBHNDL
                    CASE %IDC_BUTTON1
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON1=" + FORMAT$(%IDC_BUTTON1), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON2
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON2=" + FORMAT$(%IDC_BUTTON2), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON3
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON3=" + FORMAT$(%IDC_BUTTON3), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON4
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON4=" + FORMAT$(%IDC_BUTTON4), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON5
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON5=" + FORMAT$(%IDC_BUTTON5), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON6
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON6=" + FORMAT$(%IDC_BUTTON6), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON7
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON7=" + FORMAT$(%IDC_BUTTON7), _
                                %MB_SYSTEMMODAL
                        END IF
                    CASE %IDC_BUTTON8
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            lpcc.lStructSize=SIZEOF(lpcc)
                            lpcc.hwndOwner=CBHNDL
                            lpcc.lpCustColors=VARPTR(lpCustColor(0))
                            result=ChooseColor(lpcc)
                            IF result<>0 THEN
                                'Re-Create background color brush
                                bakcol=lpcc.rgbResult
                                DeleteObject hBrush1
                                lb.lbStyle=%BS_SOLID
                                lb.lbColor=bakcol
                                hBrush1=CreateBrushIndirect(lb)
                                FOR x=%IDC_BUTTON1 TO %IDC_BUTTON9
                                    CONTROL REDRAW CBHNDL, x
                                NEXT
                            END IF
                        END IF
                    CASE %IDC_BUTTON9
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            lpcc.lStructSize=SIZEOF(lpcc)
                            lpcc.hwndOwner=CBHNDL
                            lpcc.lpCustColors=VARPTR(lpCustColor(0))
                            result=ChooseColor(lpcc)
                            IF result<>0 THEN
                                forcol=lpcc.rgbResult
                                FOR x=%IDC_BUTTON1 TO %IDC_BUTTON9
                                    CONTROL REDRAW CBHNDL, x
                                NEXT
                            END IF
                        END IF
                    CASE %IDC_TEXTBOX1
                    CASE %IDC_CHECKBOX1
                    CASE %IDC_OPTION1
                    CASE %IDC_COMBOBOX1
    
                END SELECT
        END SELECT
    
    END FUNCTION
    '--------------------------------------------------------------------------------
    
    '--------------------------------------------------------------------------------
    '   ** Sample Code **
    '--------------------------------------------------------------------------------
    FUNCTION SampleComboBox(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lCount AS _
        LONG) AS LONG
        LOCAL i AS LONG
        FOR i = 1 TO lCount
            COMBOBOX ADD hDlg, lID, "Test Item #" + FORMAT$(i)
        NEXT i
    END FUNCTION
    '--------------------------------------------------------------------------------
    
    FUNCTION ButtonSubClassProc(BYVAL hWnd&, BYVAL wMsg&, BYVAL wParam&, BYVAL lParam&) AS LONG
    
        SELECT CASE wMsg&
            CASE %WM_SETFOCUS
                DefButton=hWnd&
            CASE %WM_KILLFOCUS
                DefButton=0
        END SELECT
    
        FUNCTION = CallWindowProc(MainProc, hWnd&, wMsg&, wParam&, lParam&)
    END FUNCTION
    
    '--------------------------------------------------------------------------------
    
    '--------------------------------------------------------------------------------
    '   ** Dialogs **
    '--------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    #PBFORMS Begin Dialog %IDD_DIALOG1->->
        LOCAL hDlg AS DWORD
    
    
        DIALOG NEW hParent, "Ownerdrawn Buttons and the Enter Key", 69, 76, 217, _
            119, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR _
            %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR _
            %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_WINDOWEDGE OR _
            %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Button1", 5, 5, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON2, "Button2", 5, 20, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON3, "Button3", 5, 35, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON4, "Button4", 5, 50, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON5, "Button5", 5, 65, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON6, "Button6", 5, 80, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON7, "Button7", 5, 95, 50, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON8, "Change Button Background Color", _
            75, 5, 140, 15, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON9, "Change Button Text Color", 75, 20, _
            140, 15, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
        CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX1, "TextBox1", 75, 40, 100, 13
        CONTROL ADD CHECKBOX, hDlg, %IDC_CHECKBOX1, "CheckBox1", 75, 55, 100, 10
        CONTROL ADD OPTION, hDlg, %IDC_OPTION1, "Option1", 75, 65, 100, 10
        CONTROL ADD COMBOBOX, hDlg, %IDC_COMBOBOX1, , 75, 75, 100, 40
    
    #PBFORMS End Dialog
    
        SampleComboBox hDlg, %IDC_COMBOBOX1, 30
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
        FUNCTION = lRslt
    END FUNCTION
    '--------------------------------------------------------------------------------


    ------------------
    Adam Drake
    Drake Software

  • #2
    If you have a mix of ownerdrawn and non-ownerdrawn buttons, then still subclass all of your buttons, but alter your subclass procedure as follows to remove the default pushbutton style from the regular ones when they lose focus, so they don't keep the black default rectangle:

    Code:
    FUNCTION ButtonSubClassProc(BYVAL hWnd&, BYVAL wMsg&, BYVAL wParam&, BYVAL lParam&) AS LONG
    
        LOCAL lRet  AS LONG
    
        SELECT CASE wMsg&
            CASE %WM_SETFOCUS
                DefButton=hWnd&
            CASE %WM_KILLFOCUS
                lRet=GetWindowLong(hWnd&,%GWL_STYLE)
                IF (lRet AND %BS_OWNERDRAW)<>%BS_OWNERDRAW THEN
                    SendMessage hWnd&, %BM_SETSTYLE, %BS_PUSHBUTTON, MAKLNG(%TRUE, 0)
                END IF
                DefButton=0
        END SELECT
    
        FUNCTION = CallWindowProc(MainProc, hWnd&, wMsg&, wParam&, lParam&)
    END FUNCTION
    ------------------
    Adam Drake
    Drake Software

    Comment

    Working...
    X