Drawing custom themed buttons

Drawing custom themed buttons

Postby AlexSchaft » Wed Feb 15, 2006 5:13 am

Hi,

Apps like Windows Media player add a button to the title bar, that removes the outside frame of its window. Other apps draw a button to minimize to tray. All these are coloured according to the current xp colour theme

I don't want to put one in the title bar. I'd just like a button like the combobox to put next to a get control, which has a browse attached to it.

Has anyone done something like this, or stumbled across a way of doing this?

I don't want to keep a copy of the combo box button as a bmp, because the colours can change.

Alex
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Postby Antonio Linares » Wed Feb 15, 2006 12:41 pm

Alex,

You may use a Class TButtonBmp button. Please review samples\TestBuBm.prg
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

XP Button bitmaps

Postby AlexSchaft » Wed Feb 15, 2006 2:02 pm

Hi,

I know about those, but I want a button drawn that looks like the xp combobox arrow button. It must also use the colours of the current xp theme (like blue, silver and olive green defaults)

Alex
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Themed button

Postby AlexSchaft » Wed Feb 15, 2006 2:42 pm

Hi,

Below is some cpp code that does it:

Code: Select all  Expand view  RUN
TEMPLATE void CDialogMinTrayBtn<BASE>::MinTrayBtnDraw()
{
    if (!MinTrayBtnIsVisible())
       return;

    CDC *pDC= GetWindowDC();
    if (!pDC)
       return; // panic!

    if (IsWindowsClassicStyle())
    {
        CBrush black(GetSysColor(COLOR_BTNTEXT));
        CBrush gray(GetSysColor(COLOR_GRAYTEXT));
        CBrush gray2(GetSysColor(COLOR_BTNHILIGHT));

        // button
        if (m_bMinTrayBtnUp)
           pDC->DrawFrameControl(MinTrayBtnGetRect(), DFC_BUTTON, DFCS_BUTTONPUSH);
        else
           pDC->DrawFrameControl(MinTrayBtnGetRect(), DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED);

        // dot
        CRect btn = MinTrayBtnGetRect();
        btn.DeflateRect(2,2);
        UINT caption = MinTrayBtnGetSize().cy + (CAPTION_BUTTONSPACE * 2);
        UINT pixratio = (caption >= 14) ? ((caption >= 20) ? 2 + ((caption - 20) / 8) : 2) : 1;
        UINT pixratio2 = (caption >= 12) ? 1 + (caption - 12) / 8: 0;
        UINT dotwidth = (1 + pixratio * 3) >> 1;
        UINT dotheight = pixratio;
        CRect dot(CPoint(0,0), CPoint(dotwidth, dotheight));
        CSize spc((1 + pixratio2 * 3) >> 1, pixratio2);
        dot -= dot.Size();
        dot += btn.BottomRight();
        dot -= spc;
        if (!m_bMinTrayBtnUp)
           dot += CPoint(1,1);
        if (m_bMinTrayBtnEnabled)
        {
           pDC->FillRect(dot, &black);
        }
        else
        {
           pDC->FillRect(dot + CPoint(1,1), &gray2);
           pDC->FillRect(dot, &gray);
        }
    }
   else
   {
      // VisualStylesXP
      CRect btn = MinTrayBtnGetRect();
      int iState;
      if (!m_bMinTrayBtnEnabled)
         iState = TRAYBS_DISABLED;
      else if (GetStyle() & WS_DISABLED)
         iState = MINBS_NORMAL;
      else if (m_bMinTrayBtnHitTest)
         iState = (m_bMinTrayBtnCapture) ? MINBS_PUSHED : MINBS_HOT;
      else
         iState = MINBS_NORMAL;
      // inactive
      if (!m_bMinTrayBtnActive)
         iState += 4; // inactive state TRAYBS_Ixxx

      if (m_bmMinTrayBtnBitmap.m_hObject && _TransparentBlt)
      {
         // known theme (bitmap)
         CBitmap *pBmpOld;
         CDC dcMem;
         if (dcMem.CreateCompatibleDC(pDC) && (pBmpOld = dcMem.SelectObject(&m_bmMinTrayBtnBitmap)) != NULL)
         {
            _TransparentBlt(pDC->m_hDC, btn.left, btn.top, btn.Width(), btn.Height(), dcMem.m_hDC, 0, BMP_TRAYBTN_HEIGHT * (iState - 1), BMP_TRAYBTN_WIDTH, BMP_TRAYBTN_HEIGHT, BMP_TRAYBTN_TRANSCOLOR);
            dcMem.SelectObject(pBmpOld);
         }
      }
      else
      {
         // unknown theme (ThemeData)
         HTHEME hTheme = g_xpStyle.OpenThemeData(m_hWnd, L"Window");
         if (hTheme)
         {
            btn.top += btn.Height() / 8;
            g_xpStyle.DrawThemeBackground(hTheme, pDC->m_hDC, WP_TRAYBUTTON, iState, &btn, NULL);
            g_xpStyle.CloseThemeData(hTheme);
         }
      }
   }

    ReleaseDC(pDC);
}
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

New class help

Postby AlexSchaft » Thu Feb 16, 2006 6:39 am

Hi,

I created a new class based on tpanel, in which the paint event becomes:

Code: Select all  Expand view  RUN
METHOD Paint() CLASS QButton

  DrawQBBackground(::hWnd, ::hDc)

RETURN NIL


DrawQBBackground comes from:

Code: Select all  Expand view  RUN
#include <WinTen.h>
#include <Windows.h>
#include <ClipApi.h>

#ifdef __FLAT__
   #include <ShellApi.h>
#endif

#ifdef __HARBOUR__
   #include <hbapiitm.h>
   #include <hbdate.h>
   #include <hbset.h>
#endif
#include "uxtheme.h"

HB_FUNC( DRAWQBBACKGROUND )
{
   HTHEME hTheme;
   HDC hDc;
   HWND hWnd;
   RECT rcWnd;
   int iStateId = 1;

   hWnd    = ( HWND ) _parnl( 1 );
   hDc = ( HDC ) _parl(2);

   GetClientRect( hWnd, &rcWnd );

   hTheme = OpenThemeData(hWnd, L"BUTTON");

   if ( hTheme)
   {
      DrawThemeBackground(hTheme,
                    hDc,
                    0,
                    0,
                    &rcWnd,
                    NULL);
    _retni(1);
   }
   else
   {
    _retni(0);
   }

}


Unfortunately, I don't see anything :(

Is there a C wizard which can help me out here
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Re: New class help

Postby Enrico Maria Giordano » Thu Feb 16, 2006 8:42 am

AlexSchaft wrote:
Code: Select all  Expand view  RUN
hDc = ( HDC ) _parl(2);


Try

Code: Select all  Expand view  RUN
hDc = ( HDC ) _parnl(2);


Perils of the cast. :-)

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8718
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Themed button working

Postby AlexSchaft » Sat Feb 18, 2006 6:17 am

Thanks, that change works, along with changing the first zero to 1 in the DrawThemeBackground call, and the second parameter is 1 for normal 2 for "hot", 3 for down, and 4 for disabled.

Only problem now is detecting when mouse leaves the control. I've copied the basics from btnbmp:mousemove but no luck so far. What am I missing?

Code: Select all  Expand view  RUN
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS QButton

//   Super:MouseMove( nRow, nCol, nKeyFlags )


   if IsOverWnd( ::hWnd, nRow, nCol )
      ::nState := 2
   else
      ::nState := 1
   endif

   ::Refresh()
return nil
//---------------------------------------------------------------------------------------------//
METHOD Paint() CLASS QButton

  // 1 Regular
  // 2 Mouse over
  // 3 Down
  // 4 Disabled

  DrawQBBackground(::hWnd, ::hDc, ::nState)

RETURN NIL
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Re: Themed button working

Postby Enrico Maria Giordano » Sat Feb 18, 2006 12:40 pm

Try adding hb prefix to all the _par* and _ret* functions.

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8718
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Themed button working

Postby AlexSchaft » Sat Feb 18, 2006 12:49 pm

I don't have a problem in my C code anymore. It links and works perfectly. I now need to detect in my control events when the mouse leaves my control.

I suppose you receive mousemove while in the control, but what do you receive when the mouse moves out of the control?

Alex
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Re: Themed button working

Postby Enrico Maria Giordano » Sat Feb 18, 2006 12:54 pm

Have a look at how tooltips are managed. Or TBtnBmp states.

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8718
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Got it

Postby AlexSchaft » Sat Feb 18, 2006 1:05 pm

Hi,

It's working now, thanks.
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Re: Got it

Postby Enrico Maria Giordano » Sat Feb 18, 2006 1:08 pm

How you solved the problem?

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8718
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Working button

Postby AlexSchaft » Sat Feb 18, 2006 1:18 pm

I copied the whole btnbmp mousemove event, and removed everything I didn't need :)

Code: Select all  Expand view  RUN
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS QButton

   if ::lDrag .or. ! Empty( ::oDragCursor )
      return Super:MouseMove( nRow, nCol, nKeyFlags )
   endif

   Super:MouseMove( nRow, nCol, nKeyFlags )

   if IsOverWnd( ::hWnd, nRow, nCol )
      if !::lCaptured
        ::Capture()
        if ::nState != 2
          ::nState := 2
          ::Refresh()
        endif
      else
        ::Refresh()
      endif
   else
      if !::lCaptured
         ReleaseCapture()
        if ::nState != 1
          ::nState := 1
          ::Refresh()
        endif
      else
        ::Refresh()
      endif
   endif

   ::oWnd:SetMsg( ::cMsg )

return 0
//---------------------------------------------------------------------------------------------//
METHOD Paint() CLASS QButton

  // 1 Regular
  // 2 Mouse over
  // 3 Down
  // 4 Disabled

  DrawQBBackground(::hWnd, ::hDc, ::nState)

RETURN NIL



C Code:
Code: Select all  Expand view  RUN
#include <WinTen.h>
#include <Windows.h>
#include <ClipApi.h>

#ifdef __FLAT__
   #include <ShellApi.h>
#endif

#ifdef __HARBOUR__
   #include <hbapiitm.h>
   #include <hbdate.h>
   #include <hbset.h>
#endif
#include "uxtheme.h"

HB_FUNC( DRAWQBBACKGROUND )
{
   HTHEME hTheme;
   HDC hDc;
   HWND hWnd;
   RECT rcWnd;
   int iStateId = 1;

   hWnd    = ( HWND ) _parnl( 1 );
   hDc = ( HDC ) _parnl(2);

   GetClientRect( hWnd, &rcWnd );

   hTheme = OpenThemeData(hWnd, L"COMBOBOX");

   if ( hTheme)
   {
      DrawThemeBackground(hTheme,
                    hDc,
                    1,
                    ( ISNUM(3) ? _parni( 3 ) : 1 ),
                    &rcWnd,
                    NULL);

    CloseThemeData(hTheme);
    _retni(1);
   }
   else
   {
    _retni(0);
   }

}
User avatar
AlexSchaft
 
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa



Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 67 guests