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

Controlled Ownerdraw Buttons

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

  • PBWin Controlled Ownerdraw Buttons

    This is an exercise to to explore and check if a normal control with Ownerdrawn routines can be managed dynamically, without subclassing, by the program aplication similarly how standard or customer controls are controlled with SendMessage functions. To achieve this I make an extensive use of CONTROL SET/GET statements with a very good results. In this program the eight possible statements per button control are used. See equate definitions on source code.

    For more customizable handlers on dynamic Ownerdrawn some different design will be needed. Is a work to do on next exercise. Is not fully developed but in this stage is entirely usable. Needs improvements mainly related to speed of the cursor over buttons. Comments or suggestions about this are welcome.

    A second intention of this program is check and see a new button design with slip and hover styles. These new buttons, in big size, can contain inside other several and miscellaneous dynamic information.

    10/11/2009 Small changes on code. Zip file changed with corrections.

    Code:
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' NButtons                        version 1c       Jordi Vallès       08/11/2009
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' This program has two intentions:
    '  - This is an exercise to explore and check if a normal ownerdrawn control,
    '    like buttons, can be managed dynamically by CONTROL SET/GET USER sentences
    '    in a similar way that standard or customer controls can be managed or
    '    handled with SendMessage functions. Without any subclass.
    '  - Test new button design. Execute this program and see.
    '
    ' Some ideas and code portions are borrowed from some people of PB community.
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '  - Compiled and tested with PowerBASIC 9.02 for Windows on a PC HP Pavilion
    '    with Windows Vista Home Premium SP2.
    '  - Partially tested on Windows XP.
    '  - Code posted here is released to Public Domain. Use at your own risk.
    '  - Developed using the José Roca SED editor 2.01
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' SED_PBWIN
    
    #Compiler PBWin 9
    #Compile Exe
    #Dim All
    
    #Debug Error OFF                    'catch array/pointer errors - OFF in production
    #Debug Display OFF                  'display untrapped errors   - OFF in production
    #Tools OFF                          'use ON only when needed for Trace/Profile/CallStk
    
    #Resource "NButtons.pbr"            'needed, see resource file
    
    #Include Once "Win32Api.inc"
    #Include "DDebug.inc"               'only for debug
    
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    %IDC_DISABLE   = 111       'checkbox for disable ownerdrawn buttons
    %IDB_BUTTON11  = 121       'standard button identifier
    
    '--- all ownerdrawn buttons are 900's (must be) ---
    %IDB_EXIT      = 911
    %IDB_BUTTON21  = 921
    %IDB_BUTTON22  = 922
    %IDB_BUTTON23  = 923
    %IDB_BUTTON24  = 924
    %IDB_BUTTON25  = 925
    %IDB_BUTTON31  = 931
    %IDB_BUTTON32  = 932
    %IDB_BUTTON41  = 941
    %IDB_BUTTON42  = 942
    %IDB_BUTTON43  = 943
    %IDB_BUTTON44  = 944
    
    '--- Equates to be used in CONTROL SET/GET USER button controls ---
    %B_TXTCOLOR    = 1         ' - Button's text color
    %B_TXTFORMAT   = 2         ' - Specifies the method of formatting the text. See DrawText API explanations,
                               '   if not specified the default is: %DT_SINGLELINE Or %DT_VCENTER Or %DT_CENTER.
                               '   Left side is compute after image, if exist. If image exists and vertical
                               '   position is set below image to max left side.
    %B_TXTVTPOS    = 3         ' - Vertical offset, in pixels, from top to put text,
                               '   if a value is given the %DT_VCENTER format option is ignored
    %B_BMPHANDLER  = 4         ' - If a bmp to be show in button set here the handler,
                               '   mask color for transparent images is Magenta, RGB(255,0,255)
    %B_BMPOFFSET   = 5         ' - Horizontal and vertical offset, in pixels, from button upper-left corner,
                               '   use Mak(Long,horiz,vert) to specify values
    %B_BMPSIZE     = 6         ' - Destination image size if different of source image size,
                               '   use Mak(Long,width,height) to specify values in pixels.
    %B_BUTTONSLIP  = 7         ' - Button Slip in pixels, default is 3 if not specified
    %B_BTNHOVER    = 8         ' - Reserved to pass information from %WM_SETCURSOR to %WM_DRAWITEM messages
    
    $APPNAME       = "Some Buttons - 1c"    'application title
    
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Global ghDlg    As Dword
    Global hBmp()   As Dword
    Global hFont()  As Dword
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    '   ** Main Application Entry Point **
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    Function WinMain(ByVal CurInst As Dword, _
                     ByVal PrvInst As Dword, _
                     ByVal CmdLine As Asciiz Ptr, _
                     ByVal CmdShow As Long) As Long
       Local signature  As Asciiz * 100
    
    gDebugFlag = %TRUE
    
       '--- only one instance of this program is allowed ---
       signature = $APPNAME + $APPNAME + $APPNAME
       If CreateMutex(ByVal 0, 1, signature) Then
          If GetLastError = %ERROR_ALREADY_EXISTS Then Exit Function
       End If
    
       Redim hBmp(1 to 5)
       hBmp(1) = LoadImage(GetModuleHandle(ByVal %NULL), "#105", %IMAGE_BITMAP, 0, 0, 0)
       hBmp(2) = LoadImage(GetModuleHandle(ByVal %NULL), "#107", %IMAGE_BITMAP, 0, 0, 0)
       hBmp(3) = LoadImage(GetModuleHandle(ByVal %NULL), "#111", %IMAGE_BITMAP, 0, 0, 0)
       hBmp(4) = LoadImage(GetModuleHandle(ByVal %NULL), "#112", %IMAGE_BITMAP, 0, 0, 0)
       hBmp(5) = LoadImage(GetModuleHandle(ByVal %NULL), "#113", %IMAGE_BITMAP, 0, 0, 0)
    
       Redim hFont(1 To 2)
       Font New "Symbol", 12, 0, 0, 0, 0 To hFont(1)
       Font New "Arial",   9, 0, 0, 0, 0 To hFont(2)
    
       MainDlg %HWND_DESKTOP
    End Function
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    Function MainDlg(hParent As Dword) As Long
    
       Dialog New hParent, $APPNAME,  , , 267, 196, %WS_CAPTION Or %WS_SYSMENU Or %WS_MINIMIZEBOX To ghDlg
       Dialog Set Icon ghDlg, "#101"
    
       Control Add Button,   ghDlg, %IDB_EXIT,     "Exit",            217, 176, 40, 16, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_EXIT,     %B_BMPHANDLER, hBmp(2)
       Control Set User      ghDlg, %IDB_EXIT,     %B_BMPOFFSET, Mak(Long,7,8)
    
       Control Add Button,   ghDlg, %IDB_BUTTON11, "Standard Button",  11, 176, 70, 16
    
       Control Add CheckBox, ghDlg, %IDC_DISABLE,  "Disable ownerdrawn buttons", 100, 178, 100, 13
    
       Control Add Button,   ghDlg, %IDB_BUTTON21, "Red",              11, 10, 70, 16, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON21, %B_TXTCOLOR, %RGB_DARKRED
       Control Set User      ghDlg, %IDB_BUTTON21, %B_BMPHANDLER, hBmp(1)
       Control Set User      ghDlg, %IDB_BUTTON21, %B_BMPOFFSET, Mak(Long,5,8)
    
       Control Add Button,   ghDlg, %IDB_BUTTON22, "Green",            11, 32, 70, 16, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON22, %B_TXTCOLOR, %RGB_GREEN
       Control Set User      ghDlg, %IDB_BUTTON22, %B_BMPHANDLER, hBmp(1)
       Control Set User      ghDlg, %IDB_BUTTON22, %B_BMPOFFSET, Mak(Long,5,8)
    
       Control Add Button,   ghDlg, %IDB_BUTTON23, "Blue",             11, 54, 70, 16, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON23, %B_TXTCOLOR, %RGB_MEDIUMBLUE
       Control Set User      ghDlg, %IDB_BUTTON23, %B_BMPHANDLER, hBmp(1)
       Control Set User      ghDlg, %IDB_BUTTON23, %B_BMPOFFSET, Mak(Long,5,8)
    
       Control Add Button,   ghDlg, %IDB_BUTTON24, "Magenta",          11, 76, 70, 16, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON24, %B_TXTCOLOR, %RGB_MAGENTA
       Control Set User      ghDlg, %IDB_BUTTON24, %B_BMPHANDLER, hBmp(1)
       Control Set User      ghDlg, %IDB_BUTTON24, %B_BMPOFFSET, Mak(Long,5,8)
    
       Control Add Button,   ghDlg, %IDB_BUTTON25, "Push here!",       11, 110, 70, 16, %BS_OWNERDRAW
    
       Control Add Button,   ghDlg, %IDB_BUTTON31, "S",                11, 142, 30, 22, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON31, %B_BUTTONSLIP, 2
       Control Add Button,   ghDlg, %IDB_BUTTON32, "W",                51, 142, 30, 22, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON32, %B_BUTTONSLIP, 2
    
       Control Add Button,   ghDlg, %IDB_BUTTON41, "William" + $Cr + "Shakespeare" + $Cr + "(1564 - 1616)", _
                                                                      100, 10, 68, 65, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON41, %B_BMPHANDLER, hBmp(5)
       Control Set User      ghDlg, %IDB_BUTTON41, %B_BMPOFFSET,  Mak(Long,5,5)
       Control Set User      ghDlg, %IDB_BUTTON41, %B_TXTFORMAT,  %DT_CENTER
       Control Set User      ghDlg, %IDB_BUTTON41, %B_TXTVTPOS,   52
       Control Set User      ghDlg, %IDB_BUTTON41, %B_BUTTONSLIP, 5
    
       Control Add Button,   ghDlg, %IDB_BUTTON42, "Vincent" + $Cr + "van Gogh" + $Cr + "(1853 - 1890)", _
                                                                      187, 10, 68, 65, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON42, %B_BMPHANDLER, hBmp(4)
       Control Set User      ghDlg, %IDB_BUTTON42, %B_BMPOFFSET,  Mak(Long,5,5)
       Control Set User      ghDlg, %IDB_BUTTON42, %B_TXTFORMAT,  %DT_CENTER
       Control Set User      ghDlg, %IDB_BUTTON42, %B_TXTVTPOS,   52
       Control Set User      ghDlg, %IDB_BUTTON42, %B_BUTTONSLIP, 5
    
       Control Add Button,   ghDlg, %IDB_BUTTON43, "Wolfgang Amadeus Mozart (1756 - 1791)", _
                                                                      100, 90, 155, 48, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON43, %B_BMPHANDLER, hBmp(3)
       Control Set User      ghDlg, %IDB_BUTTON43, %B_BMPOFFSET,  Mak(Long,5,5)
       Control Set User      ghDlg, %IDB_BUTTON43, %B_TXTFORMAT,  %DT_CENTER
       Control Set User      ghDlg, %IDB_BUTTON43, %B_TXTVTPOS,   48
       Control Set User      ghDlg, %IDB_BUTTON43, %B_BUTTONSLIP, 5
    
       Control Add Button,   ghDlg, %IDB_BUTTON44, "W. A. Mozart",    100, 148, 87, 22, %BS_OWNERDRAW
       Control Set User      ghDlg, %IDB_BUTTON44, %B_BMPHANDLER, hBmp(3)
       Control Set User      ghDlg, %IDB_BUTTON44, %B_BMPOFFSET,  Mak(Long,6,6)
       Control Set User      ghDlg, %IDB_BUTTON44, %B_BMPSIZE,    Mak(Long,20,20)
       Control Set User      ghDlg, %IDB_BUTTON44, %B_BUTTONSLIP, 4
    
       Control Set Font      ghDlg, %IDB_BUTTON31, hFont(1)
       Control Set Font      ghDlg, %IDB_BUTTON32, hFont(1)
       Control Set Font      ghDlg, %IDB_BUTTON25, hFont(2)
    
       Dialog Show Modal ghDlg, Call CbNButtons
    End Function
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CallBack Function CbNButtons()
       Static lastbutton, currentbutton, swPushed As Long
       Local cClr, lFormat, Slip, Xin, Yin, uRet, hImg, oImg, sImg, vPos As Long
       Local jj, sW, sH, oW, oH As Long
       Local hBrush, hMemDC, hPen As Dword
       Local txt            As String
       Local lpdis          As DRAWITEMSTRUCT Ptr
       Local ps             As PAINTSTRUCT
       Local bm             As BITMAP
       Local rct, rcd       As RECT
       Local gRect          As GRADIENT_RECT
       Dim vert(1)          As TRIVERTEX
    
       Select Case As Long Cb.Msg
    
          Case %WM_SETCURSOR
             If Cb.wParam <> Cb.Hndl Then        'mouse is over a control
                currentbutton = GetDlgCtrlID(Cb.wParam)
                If currentbutton > 900 Then
                   If lastbutton = 0 Then
                      Control Set User Cb.Hndl, currentbutton, %B_BTNHOVER, 1
                      Control Redraw Cb.Hndl, currentbutton
                      lastbutton = currentbutton
                   End If
                End If
             Else
                swPushed = %FALSE
                If lastbutton Then
                   Control Set User Cb.Hndl, lastbutton, %B_BTNHOVER, 0
                   Control Redraw Cb.Hndl, lastbutton
                   lastbutton = 0
                Else
                   Function = %TRUE  :  Exit Function
                End If
             End If
    
          Case %WM_NCACTIVATE
             Static hWndSaveFocus As Dword
             If IsFalse Cb.wParam Then
                hWndSaveFocus = GetFocus()
             ElseIf hWndSaveFocus Then
                SetFocus(hWndSaveFocus)
                hWndSaveFocus = 0
             End If
    
          Case %WM_COMMAND
             Select Case As Long Cb.Ctl
    
                Case %IDCANCEL, %IDB_EXIT
                   If Cb.CtlMsg = %BN_CLICKED Then Dialog End Cb.Hndl, 0
    
                Case %IDB_BUTTON25            'if black button then ...
                   Static b25 As Long
                   Incr b25
    
                   Control Set User Cb.Hndl, %IDB_BUTTON24, %B_TXTCOLOR,   Iif(b25 Mod 2, %RGB_DARKORANGE, %RGB_MAGENTA)
                   Control Set User Cb.Hndl, %IDB_BUTTON24, %B_BMPHANDLER, Iif(b25 Mod 2, 0, hBmp(1))
                   Control Set Text Cb.Hndl, %IDB_BUTTON24, Iif$(b25 Mod 2, "Light Orange", "Magenta")
                   Control Redraw   Cb.Hndl, %IDB_BUTTON24
    
                   Control Set User Cb.Hndl, %IDB_BUTTON44, %B_BMPSIZE,   Iif(b25 Mod 2, Mak(Long,28,28), Mak(Long, 20,20))
                   Control Set User Cb.Hndl, %IDB_BUTTON44, %B_BMPOFFSET, Iif(b25 Mod 2, Mak(Long,2,2), Mak(Long,6,6))
                   Control Redraw   Cb.Hndl, %IDB_BUTTON44
    
                Case %IDB_BUTTON11            'if standard button .... move text on van Gogh button
                   Static b11 As Long
                   Incr b11
                   Control Set User Cb.Hndl, %IDB_BUTTON42, %B_TXTVTPOS, b11
                   Control Redraw   Cb.Hndl, %IDB_BUTTON42
    
                Case %IDC_DISABLE             'disable/enable all onwerdrawn buttons, except Exit
                   Control Get Check Cb.Hndl, Cb.Ctl To jj
                   If jj Then
                      For jj = 921 To 944  :  Control Disable Cb.Hndl, jj  :  Next
                   Else
                      For jj = 921 To 944  :  Control Enable Cb.Hndl, jj  :  Next
                   End If
    
                End Select
    
          Case %WM_DRAWITEM
             lpdis = Cb.Lparam
             Control Get Text Cb.Hndl, Cb.Ctl To txt
             rct = @lpdis.rcItem  :  rcd = rct
    
             BeginPaint @lpdis.hwndItem, ps
                Select Case As Long Cb.Ctl
                   Case %IDB_EXIT To %IDB_BUTTON44                       '911 to 944
                      Control Get User ghDlg, Cb.Ctl, %B_BUTTONSLIP To Slip
                      If Slip <= 0 Then Slip = 3
    
                      '===== some parts of code are repeated in =====
                      '      the interest of speed and clarity
    
                      Control Get User ghDlg, Cb.Ctl, %B_BTNHOVER To uRet
    
                      '--- if button is hover ---
                      If uRet Or swPushed Then               'called from WM_SETCURSOR message ?
                         swPushed = %FALSE
                         Control Set User ghDlg, Cb.Ctl, %B_BTNHOVER, 0
                         hBrush = CreateSolidBrush(GetSysColor(%COLOR_BTNFACE))
                         FillRect @lpdis.hDC, rct, hBrush
    
                         hPen = CreatePen(%PS_SOLID, 1, %LTGRAY)               'shadow
                         SelectObject @lpdis.hDC, hPen
                         hBrush = CreateSolidBrush(%LTGRAY)
                         SelectObject @lpdis.hDC, hBrush
                         RoundRect @lpdis.hDC, rct.nLeft+Slip, rct.nTop+Slip, rct.nRight, rct.nBottom, 5, 5
                         DeleteObject SelectObject(@lpdis.hDC, hPen)
    
                         hPen = CreatePen(%PS_SOLID, 1, %BLACK)                'button
                         SelectObject @lpdis.hDC, hPen
                         hBrush = CreateSolidBrush(%WHITE)  ' RGB(250,250,250))
                         SelectObject @lpdis.hDC, hBrush
                         RoundRect @lpdis.hDC, rct.nLeft, rct.nTop, rct.nRight-Slip, rct.nBottom-Slip, 5, 5
                         DeleteObject SelectObject(@lpdis.hDC, hPen)
                         If @lpdis.CtlId = currentbutton Then
                            GoSub FillButtonHover                                                   '<<<<<
                         Else
                            GoSub FillButtonFree                                                    '<<<<<
                         End If
    
                      '--- if button is pushed ---
                      ElseIf (@lpdis.itemState And %ODS_SELECTED) Then
                         swPushed = %TRUE
                         hBrush = CreateSolidBrush(GetSysColor(%COLOR_BTNFACE))
                         FillRect @lpdis.hDC, rct, hBrush
    
                         hBrush = CreateSolidBrush(GetSysColor(%COLOR_BTNHILIGHT))
                         RoundRect @lpdis.hDC, rct.nLeft+Slip, rct.nTop+Slip, rct.nRight, rct.nBottom, 5, 5
                         Gosub FillButtonPushed                                                      '<<<<<
                         rct.nTop = Slip  :  rct.nLeft = Slip
    
                      '--- if button is in rest state ---
                      Else
                         swPushed = %FALSE
                         hBrush = CreateSolidBrush(GetSysColor(%COLOR_BTNFACE))
                         FillRect @lpdis.hDC, rct, hBrush
    
                         hPen = CreatePen(%PS_SOLID, 1, %LTGRAY)               'shadow
                         SelectObject @lpdis.hDC, hPen
                         hBrush = CreateSolidBrush(%LTGRAY)
                         SelectObject @lpdis.hDC, hBrush
                         RoundRect @lpdis.hDC, rct.nLeft+Slip, rct.nTop+Slip, rct.nRight, rct.nBottom, 5, 5
                         DeleteObject SelectObject(@lpdis.hDC, hPen)
    
                         hPen = CreatePen(%PS_SOLID, 1, %BLACK)                'button
                         SelectObject @lpdis.hDC, hPen
                         hBrush = CreateSolidBrush(RGB(250,250,250))
                         SelectObject @lpdis.hDC, hBrush
                         RoundRect @lpdis.hDC, rct.nLeft, rct.nTop, rct.nRight-Slip, rct.nBottom-Slip, 5, 5
                         DeleteObject SelectObject(@lpdis.hDC, hPen)
                         GoSub FillButtonFree                                                        '<<<<<
                      End If
    
                      '===== this part is common to three previous states =====
    
                      '--- if bmp image defined put inside button ---
                      Control Get User ghDlg, Cb.Ctl, %B_BMPHANDLER To hImg
                      If hImg Then
                         Control Get User ghDlg, Cb.Ctl, %B_BMPSIZE To sImg
                         Control Get User ghDlg, Cb.Ctl, %B_BMPOFFSET To oImg
                         oW = Lo(Integer, oImg)
                         oH = Hi(Integer, oImg)
                         GetObject hImg, SizeOf(bm), bm
                         hMemDC = CreateCompatibleDC(@lpdis.hDC)
                         SelectObject hMemDC, hImg
                         If sImg = 0 Then
                            sW = bm.bmWidth
                            sH = bm.bmHeight
                         Else
                            sW = Lo(Integer, sImg)
                            sH = Hi(Integer, sImg)
                         End If
                         TransparentBlt(@lpdis.hDC, rct.nLeft+oW, rct.nTop+oH, sW, sH, _
                                        hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, RGB(255,0,255))
                         DeleteDC hMemDc
                      End If
    
                      '--- prepare text color ---
                      Control Get User ghDlg, Cb.Ctl, %B_TXTCOLOR To cClr
                      SetBkMode @lpdis.hDC, %TRANSPARENT
                      If (@lpdis.itemState And %ODS_DISABLED) Then
                         SetTextColor @lpdis.hDC, GetSysColor(%COLOR_GRAYTEXT)
                      Else
                         SetTextColor @lpdis.hDC, cClr
                      End If
    
                      '--- prepare text format ---
                      rct.nLeft = Iif((@lpdis.itemState And %ODS_SELECTED), sW+oW+Slip, sW+oW)
                      rct.nRight = Iif((@lpdis.itemState And %ODS_SELECTED), rct.nRight, rct.nRight-Slip)
                      Control Get User ghDlg, Cb.Ctl, %B_TXTFORMAT To lFormat
                      Control Get User ghDlg, Cb.Ctl, %B_TXTVTPOS To vPos
                      If lFormat Then
                         If vPos Then
                            lFormat = lFormat And (-1 -%DT_VCENTER)
                         End If
                      Else
                         If vPos Then
                            lFormat = %DT_SINGLELINE Or %DT_CENTER
                         Else
                            lFormat = %DT_SINGLELINE Or %DT_VCENTER Or %DT_CENTER   'default format
                         End If
                      End If
    
                      If vPos Then
                         rct.nTop = Iif((@lpdis.itemState And %ODS_SELECTED), vPos+Slip, vPos)
                         If vPos > (oH + sH) Then                  'if below image set to max left
                            rct.nLeft = Iif((@lpdis.itemState And %ODS_SELECTED), Slip, 0)
                         End If
                      Else
                         rct.nTop = Iif((@lpdis.itemState And %ODS_SELECTED), rct.nTop+Slip, rct.nTop)
                      End If
    
                      '--- and finally write text on button ---
                      DrawText @lpdis.hDC, ByVal StrPtr(txt), -1, ByVal VarPtr(rct), lFormat
    
                End Select
    
             EndPaint @lpdis.hwndItem, ps        'alea jacta est
             Function = %TRUE  :  Exit Function
    
          Case %WM_DESTROY
             For jj = 1 To Ubound(hBmp)  :  If hBmp(jj) Then DeleteObject hBmp(jj) :  Next jj
             For jj = 1 To Ubound(hFont) :  If hFont(jj) Then Font End hFont(jj)   :  Next jj
    
       End Select
       Exit Function                 'end of callback
    
    '========================================================
    ' this 3 subroutines are similar but are coded and called
    ' separately on benefit of better performmance
    '========================================================
    
    '--- fill button when button is pushed ---
    '    gradient from almost white to blue
    FillButtonPushed:
       Xin = @lpdis.rcItem.nRight - @lpdis.rcItem.nLeft
       Yin = @lpdis.rcItem.nBottom - @lpdis.rcItem.nTop
       vert(0).x      = Slip+1
       vert(0).y      = Slip+1
       vert(0).Red    = &hF600
       vert(0).Green  = &hFA00
       vert(0).Blue   = &hFF00
       vert(0).Alpha  = &h0000
       vert(1).x      = Xin-1
       vert(1).y      = Yin-1
       vert(1).Red    = &hA800
       vert(1).Green  = &hE000
       vert(1).Blue   = &hF800
       vert(1).Alpha  = &h0000
       gRect.UpperLeft  = 0
       gRect.LowerRight = 1
       GradientFill @lpdis.hDC, vert(0), 2, gRect, 1, %GRADIENT_FILL_RECT_V
       SetPixel @lpdis.hDC, @lpdis.rcItem.nLeft+Slip+1,  @lpdis.rcItem.nTop+Slip+1, %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nRight-2,      @lpdis.rcItem.nTop+Slip+1, %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nLeft+Slip+1,  @lpdis.rcItem.nBottom-2,   %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nRight-2,      @lpdis.rcItem.nBottom-2,   %BLACK
       Return
    
    '--- when cursor travel hover button ---
    '    gradient from almost white to light blue
    FillButtonHover:
       Xin = @lpdis.rcItem.nRight - @lpdis.rcItem.nLeft
       Yin = @lpdis.rcItem.nBottom - @lpdis.rcItem.nTop
       vert(0).x      = 1
       vert(0).y      = 1
       vert(0).Red    = &hFF00
       vert(0).Green  = &hFF00
       vert(0).Blue   = &hFF00
       vert(0).Alpha  = &h0000
       vert(1).x      = Xin-(Slip+1)
       vert(1).y      = Yin-(Slip+1)
       vert(1).Red    = &hD800
       vert(1).Green  = &hF000
       vert(1).Blue   = &hFD00
       vert(1).Alpha  = &h0000
       gRect.UpperLeft  = 0
       gRect.LowerRight = 1
       GradientFill @lpdis.hDC, vert(0), 2, gRect, 1, %GRADIENT_FILL_RECT_V
       SetPixel @lpdis.hDC, @lpdis.rcItem.nLeft+1,       @lpdis.rcItem.nTop+1,         %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nRight-Slip-2, @lpdis.rcItem.nTop+1,         %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nLeft+1,       @lpdis.rcItem.nBottom-Slip-2, %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nRight-Slip-2, @lpdis.rcItem.nBottom-Slip-2, %BLACK
       Return
    
    '--- called when the button is at rest ---
    '    gradient from white to light grey
    FillButtonFree:
       Xin = @lpdis.rcItem.nRight - @lpdis.rcItem.nLeft
       Yin = @lpdis.rcItem.nBottom - @lpdis.rcItem.nTop
       vert(0).x      = 1
       vert(0).y      = 1
       vert(0).Red    = &hFF00
       vert(0).Green  = &hFF00
       vert(0).Blue   = &hFF00
       vert(0).Alpha  = &h0000
       vert(1).x      = Xin-(Slip+1)
       vert(1).y      = Yin-(Slip+1)
       vert(1).Red    = &hE000
       vert(1).Green  = &hE000
       vert(1).Blue   = &hE000
       vert(1).Alpha  = &h0000
       gRect.UpperLeft  = 0
       gRect.LowerRight = 1
       GradientFill @lpdis.hDC, vert(0), 2, gRect, 1, %GRADIENT_FILL_RECT_V
       SetPixel @lpdis.hDC, @lpdis.rcItem.nLeft+1,       @lpdis.rcItem.nTop+1,         %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nRight-Slip-2, @lpdis.rcItem.nTop+1,         %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nLeft+1,       @lpdis.rcItem.nBottom-Slip-2, %BLACK
       SetPixel @lpdis.hDC, @lpdis.rcItem.nRight-Slip-2, @lpdis.rcItem.nBottom-Slip-2, %BLACK
       Return
    
    End Function
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    'eof
    All files needed are supplied in the zip attached.
    Attached Files
    Last edited by Jordi Vallès; 10 Nov 2009, 12:23 PM.

  • #2
    New and more complete version. Previous limitations has been bypassed using dynamic memory allocations to hold all data needed for each control. Also the buttons could contain variable information, like counters or indicators, within them. Additionally an Statusbar has been added to show some degree of customization with Ownerdrawn contro. In it his sample the different parts have a gradient background with ToolTips with title and icon.
    Attached Files

    Comment

    Working...
    X