Announcement

Collapse
No announcement yet.

Ownerdraw buttons

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

  • Ownerdraw buttons

    I'm using a button with Ownerdraw style.
    As aspected, the parent window of the button receive a WM_DRAWITEM message whenever I need to repaint the button area.
    The problem is that this message is received by the parent only if I "push" (select) the button, not when the mouse go over and leave it, so I can't draw my "hover" and "not hover" aspect.
    Does anybody has a solution?
    Thank you.

  • #2
    Code:
    '*************************************************************************************'
    '* MouseOverButton Custom Control Example                                            *'
    '*                                                                                   *'
    '* Example of how to create a custom control and register it, so it can be used by   *'
    '* windows and dialog boxes.                                                         *'
    '*************************************************************************************'
    
    ' Include the Win32API include file is not already included
    #IF NOT %DEF(%WINAPI)
      #INCLUDE "Win32API.inc"
    #ENDIF
    
    ' Custom message used to set the button colors
    ' WM_USER to WM_USER + 7FFF are available for custom messages
    %WM_SETCOLORS = %WM_USER + 1
    
    ' Explicitly declare the functions in this file
    DECLARE FUNCTION MouseOverButtonProc(BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
    DECLARE FUNCTION InitMouseOverButton AS DWORD
    
    '*************************************************************************************'
    '* InitMouseOverButton                                                               *'
    '*                                                                                   *'
    '* Purpose:                                                                          *'
    '* Register the MouseOverButton Window Class, which allows DDT and SDK to add this   *'
    '* control to a Dialog or Window.                                                    *'
    '*                                                                                   *'
    '* Output:                                                                           *'
    '* DWORD value indicating success for failure of registering the control. if the     *'
    '* function succeeds, the return value is an atom that uniquely identifies the class *'
    '* being registered. If the function fails zero is returned.                         *'
    '*************************************************************************************'
    FUNCTION InitMouseOverButton AS DWORD
      LOCAL ClassName  AS ASCIIZ * 32                   ' Unique class name for the control
      LOCAL wc         AS WNDCLASS                      ' Window attributes for the control
    
      ClassName        = "MouseOverButton"              ' Class name
    
      wc.Style         = %CS_HREDRAW OR %CS_VREDRAW     ' Redraw the entire window
      wc.lpfnWndPRoc   = CODEPTR(MouseOverButtonProc)   ' Message handeler function
      wc.hIcon         = %NULL                          ' No icon for the control
      wc.hCursor       = LoadCursor(%NULL, BYVAL %IDC_HAND) ' Use hand mouse cursor
      wc.hbrBackground = 0                              ' Ignored, use WM_SETCOLORS
      wc.lpszMenuName  = %NULL                          ' No menu needed for the control
      wc.lpszClassName = VARPTR(ClassName)              ' Class name
    
      FUNCTION         = RegisterClass(wc)              ' Register the custom control
    END FUNCTION
    
    '*************************************************************************************'
    '* MouseOverButtonProc                                                               *'
    '*                                                                                   *'
    '* Purpose:                                                                          *'
    '* Process messages sent to the custom control.                                      *'
    '*                                                                                   *'
    '* Input:                                                                            *'
    '* hWnd  : Handle of the control                                                     *'
    '* wMsg  : The message being sent to the control                                     *'
    '* wParam: First message parameter                                                   *'
    '* lParam: Second message parameter                                                  *'
    '*                                                                                   *'
    '* Output                                                                            *'
    '* A long interger value that is the result of the message processing and depends on *'
    '* the message.                                                                      *'
    '*************************************************************************************'
    FUNCTION MouseOverButtonProc(BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
      STATIC btnState  AS LONG                          ' 0 = Button up, 1 = Button down
      STATIC MouseOver AS LONG                          ' 0 = MouseOut, 1 = MouseOver
      STATIC ColorOver AS LONG                          ' MouseOver color
      STATIC COlorOut  AS LONG                          ' MouseOut color
      LOCAL r          AS RECT                          ' Size and positon of the control
      LOCAL szText     AS ASCIIZ * 40                   ' Text used on the control
      LOCAL hdc        AS DWORD                         ' The control DC
      LOCAL ps         AS PAINTSTRUCT                   ' Painting Information
      LOCAL hbrush     AS DWORD                         ' Colored brush used to paint
      LOCAL pt         AS POINTAPI                      ' Mouse cursor location
      LOCAL clr        AS LONG                          ' Color of the control
    
      ' Process messages
      SELECT CASE AS LONG wMsg
    
        CASE %WM_SETCOLORS                              ' Set the controls colors
          ColorOver = wParam                            ' Set MouseOver color
          ColorOut  = lParam                            ' Set MouseOut color
    
        CASE %WM_PAINT                                  ' Draw the control
          GetClientRect(hWnd, r)                        ' Size and location fo the control
          GetWindowText(hWnd, szText, SIZEOF(szText))   ' Get the text shown on the control
    
          IF MouseOver = 1 THEN                         ' Is the cursor on the control?
            clr = ColorOver                             ' Use MouseOver color
          ELSE
            clr = ColorOut                              ' Use MouseOut color
          END IF
          hbrush = CreateSolidBrush(clr)                ' Create a brush with the color
          SelectObject(hdc, hBrush)                     ' Select the brush
    
          hdc = BeginPaint(hwnd, ps)                    ' Prepare the control for painting
    
          FillRect hdc, r, hbrush                       ' Draw a solid rectangle
    
          IF btnState = 1 THEN                          ' Is the button being clicked?
            DrawEdge(hdc, r, %EDGE_SUNKEN, %BF_RECT)    ' Draw a sunken edge
          ELSE
            DrawEdge(hdc, r, %EDGE_RAISED, %BF_RECT)    ' Draw a raised edge
          END IF
    
          SetBkColor(hdc, clr)                          ' Set the text background color
          SetTextColor(hdc, %BLACK)                     ' Set the text color
    
          ' Draw the text
          DrawText(hdc, szText, -1, r, %DT_CENTER OR %DT_VCENTER OR %DT_SINGLELINE)
    
          DeleteObject(hBrush)                          ' Delete the brush
          EndPaint(hwnd, ps)                            ' End painting
    
    
      CASE %WM_MOUSEMOVE:                               ' The mouse moved over the control
        IF MouseOver = 0 THEN                           ' Was the mouse already over?
          SetCapture(hWnd)                              ' Capture the mouse
          MouseOver = 1                                 ' Mouse is over the control
          InvalidateRect(hwnd, BYVAL %NULL, %TRUE)      ' Repaint the control
        ELSE
          GetWindowRect(hwnd, r)                        ' Size and location of the control
          GetCursorPos(pt)                              ' Location of the mouse cursor
          IF PtInRect(r, pt.x, pt.y ) = %FALSE THEN     ' Is cursor still over the control
            CALL ReleaseCapture()                       ' Stop capturing the mouse
            MOuseOver = 0                               ' Mouse is not over the control
            InvalidateRect(hwnd, BYVAL %NULL, %TRUE)    ' Repaint the control
          END IF
        END IF
        EXIT FUNCTION
    
      CASE %WM_LBUTTONUP:                               ' Left mouse button is now up
        btnState = 0                                    ' Button is up
        CALL ReleaseCapture()                           ' Stop capturing the mouse
        MOuseOver = 0                                   ' Mouse is not over the control
        InvalidateRect(hwnd, BYVAL %NULL, %TRUE)        ' Repaint the control
    
        ' Send a BN_CLICKED message to the controls parent window procedure
        SendMessage(GetParent(hwnd), %WM_COMMAND, MAKLNG(GetWindowLong(hwnd, %GWL_ID), %BN_CLICKED), hwnd)
        EXIT FUNCTION
    
      CASE %WM_LBUTTONDOWN:                             ' Left mouse button is down
        btnState = 1                                    ' Button is down
        InvalidateRect(hwnd, BYVAL %NULL, %TRUE)        ' Redraw the button
        EXIT FUNCTION
    
      END SELECT
    
      ' Pass any messages we did not process onto Windows to handle
      FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
    END FUNCTION
    Test Code:
    Code:
    COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    
    #INCLUDE "mob.inc"
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1         =  101
    %IDC_BUTTON1         = 1001
    %IDC_CUSTOMCONTROL_1 = 1002
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ' Initialization handler
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE %WM_COMMAND
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
                    CASE %IDC_BUTTON1
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            MSGBOX "%IDC_BUTTON1=" + FORMAT$(%IDC_BUTTON1), _
                                %MB_TASKMODAL
                        END IF
    
                    CASE %IDC_CUSTOMCONTROL_1
                      ? "custom"
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
       InitMouseOverButton
    
        DIALOG NEW PIXELS, hParent, "Dialog1", 105, 114, 497, 297, %WS_OVERLAPPED _
            OR %WS_BORDER OR %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
            %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
            %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
            %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Button1", 120, 24, 112, 41
        CONTROL ADD "MouseOverButton", hDlg, %IDC_CUSTOMCONTROL_1, _
            "OK", 128, 98, 127, 48, %WS_CHILD OR %WS_VISIBLE OR _
            %WS_TABSTOP, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
    #PBFORMS END DIALOG
    
        CONTROL SEND hdlg, %IDC_CUSTOMCONTROL_1, %WM_SETCOLORS, %GREEN, %YELLOW
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    Sincerely,

    Steve Rossell
    PowerBASIC Staff

    Comment


    • #3
      You have to add your own mouse tracking code to accomplish what you want. One technique is to use a timer (ie. every 100 ms) to generate an event where you test to see if the mouse is over the button control. If it is, then you force the control to redraw itself (ie. InvalidateRect call), set a flag (ie. global variable) and then when the WM_DRAWITEM message is generated, simply test the flag and draw accordingly.
      Chris Boss
      Computer Workshop
      Developer of "EZGUI"
      http://cwsof.com
      http://twitter.com/EZGUIProGuy

      Comment


      • #4
        Another approach might be to forget the button control and just draw the button direct on the dialog.. All the mouse and key messages are available there!

        You would, of course, make it look prettier than this example...
        Code:
        ' direct drawn button without using a separate control example
        ' Chris Holbrook Nov 2010
        #compile exe
        #dim all
        #include "WIN32api.inc"
        ' buttonstate values
        %mybn_clicked    = 1
        %mybn_mouseover  = 2
        %mybn_selected   = 4
        %mybn_busy   = 8
        macro mrepaint = invalidaterect cb.hndl, byval 0, %false
        '----------------------------------------------------------
        callback function CBproc
            local PS as PAINTSTRUCT
            local s, st as string
            local x, y as long
            local hDC as dword
            local pt as point
            static buttonstate as long
            static rbutton, rtext as rect
            '
            select case as long cb.msg
                case %wm_initdialog
                    setrect rbutton, 10, 10, 250, 35
                    setrect rtext, 10, 50, 250, 150
                '
                case %wm_lbuttondown
                    x = lo(word, cb.lparam)
                    y = hi(word, cb.lparam)
                    if ptinrect(rbutton, x, y) then
                        buttonstate = %mybn_busy
                        mrepaint
                        ? "you clicked"
                        buttonstate = 0
                    end if
                '
                case %wm_mousemove
                    x = lo(word, cb.lparam)
                    y = hi(word, cb.lparam)
                    if ptinrect(rbutton, x, y) then
                        buttonstate = %mybn_mouseover
                        mrepaint
                    else
                        buttonstate = 0
                        mrepaint
                    end if
                        
                '
                case %wm_keyup
                    select case as long cb.wparam
                        case %VK_RETURN
                            if buttonstate and %mybn_selected then
                                buttonstate = %mybn_busy
                                mrepaint
                                ?"you hit return"
                                buttonstate = 0
                                mrepaint
                            end if
                        case %VK_TAB
                            buttonstate = iif((buttonstate and %mybn_selected) = 0, %mybn_selected, 0)
                            mrepaint
                    end select
                '
                case %wm_paint
                    hDC = beginpaint (cb.hndl, PS)
                    select case as long buttonstate
                        case %mybn_clicked
                            s = "clicked"
                        case %mybn_mouseover
                            s = "mouseover"
                        case %mybn_selected
                            s = "selected"
                        case %mybn_busy
                            s = "busy"
                        case else
                            s = "I'm a button"
                    end select
                    fillrect hDC, rbutton, getsyscolorbrush(%COLOR_captiontext)
                    drawtext hDC, byval strptr(s), len(s), rbutton, %DT_CENTER
                    framerect hDC, rbutton, getsyscolorbrush(%COLOR_BTNTEXT)
                    s = "<TAB> to change button focus" + $crlf + _
                        "<ENTER> with focus goes busy" + $crlf + _
                        "<left-click> goes busy" + $crlf + _
                        "<mouseover>"
                    drawtext hDC, byval strptr(s), len(s), rtext, %DT_WORDBREAK
                    endpaint cb.hndl, PS
                '
            end select
            exit function
        showmsg:
            control get text cb.hndl, 1001 to st
            st += s
            control set text cb.hndl, 1001, right$(st, 200)
        return
        end function
        '----------------------------------------------------------
        function pbmain() as long
            local hd as dword
            local r as rect
        
            dialog new pixels, %hwnd_desktop, "Button without Control", _
                               0, 0, 270, 150, _
            %ws_popup or %ws_clipsiblings or %ws_visible or %ds_3dlook or _
            %ds_center or %ws_caption or %ws_sysmenu to hD
            getclientrect hd, r
            dialog show modal hd call cbproc
        end function

        Comment


        • #5
          Steve - Nice job! I like it.
          Larry Kruse

          Comment


          • #6
            http://msdn.microsoft.com/en-us/libr...(v=VS.85).aspx

            See also winuser.h, and the excellent WinUser.inc translation done by José Roca.

            Or use a mouse hook.

            Or use WinLIFT

            ...
            Last edited by Patrice Terrier; 17 Nov 2010, 05:26 PM.
            Patrice Terrier
            www.zapsolution.com
            www.objreader.com
            Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

            Comment


            • #7
              Very nice code!
              You suggest to create a new "button class", with all
              the trouble about it (i.e., using Steve's code, when you leave the
              button with left mouse clicked, the button remain "pushed". Of course
              some works can repair this wrong beahviour, but it seems like to re-invent
              the wheel)
              In any case thank you very much, I think is the right way.

              Comment


              • #8
                I posted an example similar to mine above but coded as a class. The overhead on the application code is pretty low. It shows how colors and raised/sunken edges (thanks for the example, Steve) could be used for different button states. It would be very simple to add state images.

                Here is the source code

                Comment


                • #9
                  owner draw using standard button

                  Using your helps, and some suggestion from the forum, I do this.
                  Symply subclass the button (see WM_INITDIALOG) and add BT_Subclass function. The drawing operation are in the BT_Draw for an easy reading.
                  In this way we have no trouble about mouse tracking and sending WM_COMMAND message to the parent windows, using for this the standard behaviour of the BUTTON default window procedure.
                  Note that the button has not the OWNERDAW style, an so don't use the WM_DRAWITEM in the parent window.
                  (I hope my code is better then my english)
                  What do you think?

                  Code:
                  #PBFORMS CREATED V2.01
                  '------------------------------------------------------------------------------
                  ' The first line in this file is a PB/Forms metastatement.
                  ' It should ALWAYS be the first line of the file. Other
                  ' PB/Forms metastatements are placed at the beginning and
                  ' end of "Named Blocks" of code that should be edited
                  ' with PBForms only. Do not manually edit or delete these
                  ' metastatements or PB/Forms will not be able to reread
                  ' the file correctly.  See the PB/Forms documentation for
                  ' more information.
                  ' Named blocks begin like this:    #PBFORMS BEGIN ...
                  ' Named blocks end like this:      #PBFORMS END ...
                  ' Other PB/Forms metastatements such as:
                  '     #PBFORMS DECLARATIONS
                  ' are used by PB/Forms to insert additional code.
                  ' Feel free to make changes anywhere else in the file.
                  '------------------------------------------------------------------------------
                  
                  #COMPILE EXE
                  #DIM ALL
                  
                  '------------------------------------------------------------------------------
                  '   ** Includes **
                  '------------------------------------------------------------------------------
                  #PBFORMS BEGIN INCLUDES
                  #RESOURCE "OwnerDrawButton.pbr"
                  #INCLUDE ONCE "WIN32API.INC"
                  #INCLUDE ONCE "COMMCTRL.INC"
                  #INCLUDE ONCE "PBForms.INC"
                  #PBFORMS END INCLUDES
                  
                  '------------------------------------------------------------------------------
                  
                  '------------------------------------------------------------------------------
                  '   ** Constants **
                  '------------------------------------------------------------------------------
                  #PBFORMS BEGIN CONSTANTS
                  %BUTTON_1 = 1001
                  %IDD_DIALOG1  =  101
                  #PBFORMS END CONSTANTS
                  '------------------------------------------------------------------------------
                  
                  '------------------------------------------------------------------------------
                  '   ** Declarations **
                  '------------------------------------------------------------------------------
                  DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                  DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                  #PBFORMS DECLARATIONS
                  '------------------------------------------------------------------------------
                  
                  
                  
                  
                  
                  
                  
                  GLOBAL OldButtonProc AS DWORD
                  
                  '------------------------------------------------------------------------------
                  '   ** Main Application Entry Point **
                  '------------------------------------------------------------------------------
                  FUNCTION PBMAIN()
                      ShowDIALOG1 %HWND_DESKTOP
                  END FUNCTION
                  '------------------------------------------------------------------------------
                  
                  '------------------------------------------------------------------------------
                  '   ** CallBacks **
                  '------------------------------------------------------------------------------
                  CALLBACK FUNCTION ShowDIALOG1Proc()
                      DIM hDlg AS LOCAL DWORD
                      DIM hButton AS LOCAL DWORD
                  
                      hDlg=CB.HNDL
                  
                      SELECT CASE AS LONG CB.MSG
                          CASE %WM_INITDIALOG
                              '--------------------------------------------------------------------------------
                              'Subclass the button
                              '--------------------------------------------------------------------------------
                              OldButtonProc = SetWindowLong(GetDlgItem(hDlg,%BUTTON_1), %GWL_WNDPROC, CODEPTR(BT_Subclass))
                  
                          CASE %WM_NCACTIVATE
                              STATIC hWndSaveFocus AS DWORD
                              IF ISFALSE CB.WPARAM THEN
                                  ' Save control focus
                                  hWndSaveFocus = GetFocus()
                              ELSEIF hWndSaveFocus THEN
                                  ' Restore control focus
                                  SetFocus(hWndSaveFocus)
                                  hWndSaveFocus = 0
                              END IF
                  
                          CASE %WM_COMMAND
                              ' Process control notifications
                              SELECT CASE AS LONG CB.CTL
                                  CASE %BUTTON_1
                                      IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                          MSGBOX "%BUTTON_1=" + FORMAT$(%BUTTON_1), _
                                              %MB_TASKMODAL
                                      END IF
                  
                              END SELECT
                      END SELECT
                  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, "Dialog1", 196, 127, 201, 121, %WS_POPUP OR _
                          %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
                          %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                          %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                          %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                      CONTROL ADD BUTTON, hDlg, %BUTTON_1, "Button1", 50, 30, 100, 55
                  #PBFORMS END DIALOG
                  
                      DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                  
                  #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                  #PBFORMS END CLEANUP
                  
                      FUNCTION = lRslt
                  END FUNCTION
                  '------------------------------------------------------------------------------
                  
                  
                  
                  
                  
                  
                  
                  FUNCTION BT_Subclass(BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD,BYVAL wParam AS DWORD, BYVAL lParam AS LONG) EXPORT AS LONG
                      DIM ps  AS LOCAL PAINTSTRUCT
                  
                      SELECT CASE AS LONG wMsg
                      CASE %WM_PAINT
                          BeginPaint(hWnd, ps)
                              CALL BT_Draw(hWnd,ps)
                          EndPaint(hWnd,ps)
                          FUNCTION=0
                          EXIT FUNCTION
                      END SELECT
                  
                      FUNCTION = CallWindowProc(OldButtonProc, hWnd, wMsg, wParam, lParam)
                  
                  END FUNCTION
                  
                  
                  
                  
                  
                  
                  SUB BT_Draw(hWnd AS DWORD,ps AS PAINTSTRUCT)
                      DIM hBrush      AS LOCAL DWORD
                      DIM wRect       AS LOCAL rect
                      DIM Txt         AS LOCAL STRING
                      DIM mpoint      AS LOCAL POINT
                      DIM ButtonState AS LOCAL LONG
                  
                  
                      '--------------------------------------------------------------------------------
                      'No better way found (at the moment) for determine if the muse i over the window
                      'hWnd.
                      'in any case here we can know if the mouse is over the button
                      '--------------------------------------------------------------------------------
                      CALL GetWindowRect(hWnd,wRect)
                      CALL GetCursorPos (mPoint)
                      IF PtInRect(wRect,mPoint.x,mPoint.y)        THEN ButtonState = 1  'mouse over button state
                  
                      '--------------------------------------------------------------------------------
                      'Is the button pushed?
                      '--------------------------------------------------------------------------------
                      IF (Button_GetState(hWnd) AND %BST_PUSHED)  THEN ButtonState = 2  'button is pushed (and of course, the mouse is over)
                  
                  
                  
                      SELECT CASE ButtonState
                      CASE 1  'THE MOUSE IS OVER THE BUTTON (MAY BE PUSHED TOO, SEE CASE 2)
                              hBrush = CreateSolidBrush(%RED)
                              FillRect ps.hdc, ps.rcPaint, hBrush
                              DrawEdge(ps.hdc, ps.rcPaint, %EDGE_RAISED, %BF_RECT)
                  
                  
                              '--------------------------------------------------------------------------------
                              'Draw the button text
                              '--------------------------------------------------------------------------------
                              SetBkMode ps.hdc, %TRANSPARENT
                              SetTextColor ps.hdc, %BLACK
                              Txt="MOUSE OVER"
                              DrawText ps.hdc, BYVAL STRPTR(txt), LEN(txt), BYVAL VARPTR(ps.rcPaint), (%DT_VCENTER OR %DT_SINGLELINE OR %DT_CENTER)
                  
                              DeleteObject hBrush
                  
                          CASE 2   'THE BUTTON IS PUSHED
                  
                              hBrush = CreateSolidBrush(%YELLOW)
                              FillRect ps.hdc, ps.rcPaint, hBrush
                              DrawEdge(ps.hdc, ps.rcPaint, %EDGE_SUNKEN, %BF_RECT)
                  
                  
                              '--------------------------------------------------------------------------------
                              'Draw the button text
                              '--------------------------------------------------------------------------------
                              SetBkMode ps.hdc, %TRANSPARENT
                              SetTextColor ps.hdc, %BLACK
                              Txt="BUTTON PUSHED"
                              DrawText ps.hdc, BYVAL STRPTR(txt), LEN(txt), BYVAL VARPTR(ps.rcPaint), (%DT_VCENTER OR %DT_SINGLELINE OR %DT_CENTER)
                  
                              DeleteObject hBrush
                  
                  
                          CASE ELSE  'ANY OTHER STATE O THE BUTTON
                              hBrush = CreateSolidBrush(%GREEN)
                              FillRect ps.hdc, ps.rcPaint, hBrush
                              DrawEdge(ps.hdc, ps.rcPaint, %EDGE_RAISED, %BF_RECT)
                  
                              '--------------------------------------------------------------------------------
                              'Draw the button text
                              '--------------------------------------------------------------------------------
                              SetBkMode ps.hdc, %TRANSPARENT
                              SetTextColor ps.hdc, %BLACK
                              Txt="NORMAL STATE"
                              DrawText ps.hdc, BYVAL STRPTR(txt), LEN(txt), BYVAL VARPTR(ps.rcPaint), (%DT_VCENTER OR %DT_SINGLELINE OR %DT_CENTER)
                  
                              DeleteObject hBrush
                  
                          END SELECT
                  END SUB

                  And the resource code for XP Theme (without this, no mouse over is detected)

                  Code:
                  #include "Resource.h"
                  1 24 XPTheme.xml
                  Last edited by Emanuele Colombo; 20 Nov 2010, 06:02 AM.

                  Comment

                  Working...
                  X