Announcement

Collapse
No announcement yet.

Owner Draw button themed for XP

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

  • Roger Garstang
    replied
    See...when all else fails, ask Jose. If he can't fix it, it's broke.

    ------------------
    If you aim at nothing...you will hit it.

    Leave a comment:


  • José Roca
    replied
    Theme aware XP push button that can also act as a toggle button and
    display an icon or bitmap.

    http://www.forum.it-berater.org/index.php?topic=11.0


    ------------------
    Website: http://com.it-berater.org
    SED Editor, TypeLib Browser, COM Wrappers.
    Forum: http://www.forum.it-berater.org

    Leave a comment:


  • Roger Garstang
    replied
    Didn't Jose or one of those guys post something to do just this on
    their forum??? I got the code in a zip file right in front of me.

    Even handles themed and no theme and does very nice.

    ------------------
    If you aim at nothing...you will hit it.

    Leave a comment:


  • Kev Peel
    replied
    Perhaps the "correct" method would be to call RedrawWindow in response to WM_UPDATEUISTATE?

    ------------------
    kgpsoftware.com
    Slam Database Manager - simple, but effective database system.
    PrpT Property List - kiss those complex 'options dialogs' goodbye!

    Leave a comment:


  • Simon Morgan
    replied
    Glad you found it useful, Hanns. Thanks for improving my code.

    I'd never come across %WM_UPDATEUISTATE before. I see it only came in with Win 2000. MSDN:
    An application sends the WM_UPDATEUISTATE message to change the user interface (UI) state for the specified window and all its child windows.
    Hmm, not quite sure what that means in practical terms. Hitting Alt causes the keyboard accelerator characters to be underlined, which is presumably achieved with this message, but not sure why the arrow keys cause it to be sent.

    Also, I would have thought that %WM_UPDATEUISTATE would cause a %WM_Paint to be generated if a button needed to change its appearance, but obviously not.

    Leave a comment:


  • Hanns Ackermann
    replied
    Just tried Simon's code and, hitting Left-Alt or one of the
    Arrow-Keys, encountered a problem with disappearing text and icon
    of both subclassed buttons, respectively (XP/PB8). The problem
    was cured after replacing

    "IF wMsg=%WM_PAINT THEN"
    with
    "IF wMsg=%WM_PAINT OR wMsg=%WM_UPDATEUISTATE THEN"

    I hope there are no objections...

    Thanks, Simon, for your code. This subclassing thing was really
    over my head!

    Regards, Hanns.


    ------------------


    [This message has been edited by Hanns Ackermann (edited September 23, 2006).]

    Leave a comment:


  • Simon Morgan
    replied
    Thanks, Borje.

    Well here's a much simpler way of doing XP themeing of 'special' buttons, using sub-classing rather than owner-draw, making Windows do all the work of button drawing, hotlighting, etc. No special includes are now needed.

    This code is a bit primitive at the moment - it clearly need a some arrays if there are more than two buttons to be treated in this way. The global oldProc could be avoided by storing it in the window properties with SetProp. This would also provide a separate value for each button for the address of the normal button procedure, which Windows seems to use.
    Code:
    #RESOURCE "Themed"   'include XML manifest file
    #INCLUDE "Win32API.inc"
    
    GLOBAL oldProc AS DWORD  'use for both sub-classed buttons
    
    FUNCTION SCButtonProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS LONG, _
                           BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
      LOCAL hDC AS DWORD, R AS RECT, hOldObject AS DWORD
      FUNCTION=CallWindowProc(oldProc,hWnd,wMsg,wParam,lParam)
         'done normal painting first, now add our finishing touches
      IF wMsg=%WM_PAINT THEN
        GETClientRECT hWnd,R
        hDC=GetDC(hWnd)  
          SELECT CASE GetDlgCtrlID(hWnd)
          CASE 100   'put red text on the button
             hOldObject=SelectObject(hDC,GetStockObject(%Default_GUI_Font))
             SETTEXTCOLOR hDC,%RED
             SETBKMODE hDC,%TRANSPARENT
             DRAWTEXT hDC,"Sub-classed",-1,R,%DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER
             SelectObject hDC,hOldObject
          CASE 101    'draw an ellipse on the button
             hOldObject=SelectObject (hDC,GetStockObject(%Gray_Brush))
             ELLIPSE hDC, R.nLeft+20, R.nTop+10, R.nRight-20, R.nBottom-10
             SelectObject hDC,hOldObject
          END SELECT 
        ReleaseDC hWnd,hDC   
      END IF
    END FUNCTION  
    
    CALLBACK FUNCTION ButtonProc
       STATIC hCtrl1,hCtrl2 AS DWORD 
    
       SELECT CASE CBMSG
     
       CASE %WM_INITDIALOG
         CONTROL HANDLE CBHNDL,100 TO hCtrl1
         oldProc=SETWINDOWLONG(hCtrl1,%GWL_WndProc, CODEPTR(SCButtonProc))
         CONTROL HANDLE CBHNDL,101 TO hCtrl2
         IF SETWINDOWLONG(hCtrl2,%GWL_WndProc, CODEPTR(SCButtonProc))<>oldProc THEN _
             MSGBOX "False assumption!" 'works OK using the same oldProc for both buttons
         
       CASE %WM_Destroy  
         SETWINDOWLONG hCtrl1,%GWL_WndProc, oldProc
         SETWINDOWLONG hCtrl2,%GWL_WndProc, oldProc
       END SELECT
    END FUNCTION
    
    FUNCTION PBMAIN
       LOCAL hDlg AS DWORD 
       DIALOG NEW 0,"Themed sub-classed buttons",,,150,100,%WS_CAPTION OR %WS_SYSMENU TO hDlg
       CONTROL ADD BUTTON, hDlg, 100, "",5,20,50,14 
       CONTROL ADD BUTTON, hDlg, 101, "",5,40,50,30 
       CONTROL ADD BUTTON, hDlg, 102, "Standard",5,80,50,14 'standard button for comparison
       DIALOG SHOW MODAL hDlg, CALL ButtonProc  
    END FUNCTION

    Leave a comment:


  • Borje Hagsten
    replied
    Seems like you will have to subclass the button, trap mouse-over and draw this state "by hand".

    See: http://www.codeguru.com/Cpp/controls...cle.php/c5161/


    ------------------
    PowerBASIC Staff
    ------------------
    Private web-site: http://www.tolkenxp.com/pb
    Free downloads: POFFS, incLean, PBcodec, custom controls and PB samples.

    Leave a comment:


  • Simon Morgan
    replied
    Hm, still no joy with 'hotlighting'. I came across the BCN_HOTITEMCHANGE notification message on msdn (%BCN_HOTITEMCHANGE = -1249), but I'm only getting this for normal buttons, not my owner-drawn ones. It seems that on my version of XP (Home SP2), M$ has neglected to implement the documented %ODS_HotLight state of the WM_DrawItem message for owner-drawn buttons. Perhaps it works with other types of control, otherwise it is a totally redundant facility, since WM_DrawItem is only used with owner draw.

    I suppose I could do my own hit testing in a WM_MouseMove handler, or perhaps a sub-classed button would retain its themed look, but that seems rather a lot of work just to get a button to highlight when the mouse is on it.

    Any comments or suggestions please?

    Leave a comment:


  • Simon Morgan
    started a topic Owner Draw button themed for XP

    Owner Draw button themed for XP

    the following is an attempt to address the issue of making image buttons themed when run in xp. this has been a frequent request on this forum, but hasn’t yet been answered. i actually just draw red text, but bitblting an image onto a button would be nearly as easy.

    don’t get too excited though, because my code doesn’t yet ‘hotlight’ the button by adding an orange border when the mouse cursor is on it. can anyone suggest why the %wm_drawitem message never seems to be received with the %ods_hotlight flag set?

    the code assumes that there is an xp manifest in the resource file. calling isthemeactive does not appear to be necessary because openthemedata only returns a handle if the program is running under xp and the style chosen is themed (i.e. not ‘windows classic’).

    theme.inc is by rosa meltronco and is the bottom half of the code posted at: http://www.powerbasic.com/support/pb...ad.php?t=23846
    Code:
    #resource "themed"  ‘includes xml manifest file
    #include "win32api.inc"
    #include "theme.inc"  ‘by rosa meltronco
    
    callback function ownerdrawproc
       select case cbmsg
         case %wm_drawitem       'owner draw buttons 
           dim t as drawitemstruct ptr
           dim txt$, r as rect, htheme as dword, istate as long
           t=cblparam
           r= @t.rcitem
           htheme= openthemedata(cbhndl, "button")
           if htheme then   'xp theme         
              control send cbhndl,cbwparam,%wm_erasebkgnd,@t.hdc,0 
                'avoids button acquiring square corners after being pressed
              istate=1 ' default state = %minbs_normal 
              if (@t.itemstate and %ods_inactive) then istate=5        
              if (@t.itemstate and %ods_disabled) then istate=4      
              if (@t.itemstate and %ods_hotlight) then istate=2 ' %minbs_hot       
              if (@t.itemstate and %ods_selected) then istate=3 ' %minbs_pushed       
              call drawthemebackground(htheme, @t.hdc, 1, istate, @t.rcitem, byval %null) 
              call closethemedata(htheme)
           else             'not xp or not themed
             if(@t.itemstate and %ods_selected) then
               call drawframecontrol(byval @t.hdc,@t.rcitem,%dfc_button,%dfcs_buttonpush or %dfcs_pushed)
               r.ntop=r.ntop+2 : r.nleft=r.nleft+2 'move the text 1 pixel when button pressed
             else
               call drawframecontrol(byval @t.hdc,@t.rcitem,%dfc_button,%dfcs_buttonpush)  
             end if
           end if
    
      'we've drawn the button - now put text or graphics onto it
           control get text cbhndl,cbctl to txt$
           settextcolor @t.hdc,%red
           setbkmode @t.hdc,%transparent
           drawtext @t.hdc,bycopy txt$,-1,r,%dt_singleline or %dt_center or %dt_vcenter
           function=%true
                         
       end select
    end function
    
    function pbmain
       local hdlg as dword
       dialog new 0,"themed owner draw buttons",0,0,150,100,%ws_caption or %ws_sysmenu to hdlg
       control add button, hdlg, 100, "owner draw 1",5,20,50,14 ,%ws_tabstop or %bs_ownerdraw 
       control add button, hdlg, 101, "owner draw 2",5,40,50,24 ,%ws_tabstop or %bs_ownerdraw
       control add button, hdlg, 102, "standard",5,80,50,14 'standard button for comparison
       dialog show modal hdlg, call ownerdrawproc  
    end function
Working...
X