www.pudn.com > ExpBar_src.zip > cbbutton.c


/* 
 * file           : cbbutton.c 
 * language       : ANSI/ISO C 
 * plattform      : Win32 (Windows 98/Me/NT/2000/XP) 
 * description    : implements checkbox/radio button for xp-style explorer bar 
 * 
 * revision history: 
 * ================= 
 * 
 * date:       author:           description: 
 * -------------------------------------------------------------------------- 
 * 02/17/2004  Ingo A. Kubbilun  first published version 1.0 
 */ 
 
#include  
#include  
#include  
 
#define BUTTON_HSPACE           2 
#define BUTTON_VSPACE1          6 
#define BUTTON_VSPACE2          2 
 
#define CHECK_HSPACE            4 
#define RADIO_HSPACE            4 
 
#define BUTTON_LEFT             0 
#define BUTTON_RIGHT            1 
#define BUTTON_CENTER           2 
 
static BOOL APIENTRY GetLogFontEx ( HFONT hFont, PLOGFONT pLF, UINT *puDescent ) 
{ 
  HDC             hDC = GetDC(NULL); 
  HGDIOBJ         hOldObj; 
  TEXTMETRIC      tm; 
 
  memset(pLF,0,sizeof(LOGFONT)); 
  if (!hDC) return FALSE; 
 
  if (!hFont) 
  { 
    ReleaseDC(NULL,hDC); 
    return FALSE; 
  } 
 
  hOldObj = SelectObject(hDC,hFont); 
  if (!GetTextMetrics(hDC,&tm)) 
  { 
    SelectObject(hDC,hOldObj); 
    ReleaseDC(NULL,hDC); 
    return FALSE; 
  } 
 
  if (puDescent) *puDescent = tm.tmDescent; 
 
  pLF->lfHeight         = -tm.tmAscent; 
  pLF->lfWeight         = tm.tmWeight; 
  pLF->lfItalic         = tm.tmItalic; 
  pLF->lfCharSet        = tm.tmCharSet; 
  pLF->lfQuality        = DEFAULT_QUALITY; 
  pLF->lfPitchAndFamily = tm.tmPitchAndFamily; 
  GetTextFace(hDC,sizeof(pLF->lfFaceName),pLF->lfFaceName); 
 
  SelectObject(hDC,hOldObj); 
  ReleaseDC(NULL,hDC); 
 
  return TRUE; 
} 
 
static void APIPRIVATE HandleClick ( HWND hwnd, PCBBUTTON pCBB ) 
{ 
  LONG          lStyle = GetWindowLong(hwnd,GWL_STYLE); 
 
  switch(lStyle & CBBS_TYPEMASK) 
  { 
    case CBBS_AUTOCHECKBOX: 
    case CBBS_AUTORADIOBUTTON: 
      pCBB->uButtonState ^= CBBST_CHECKED; 
      InvalidateRect(hwnd,NULL,TRUE); 
      break; 
 
    case CBBS_AUTO3STATE: 
      pCBB->uButtonState++; 
      if (pCBB->uButtonState==3) 
        pCBB->uButtonState = CBBST_UNCHECKED; 
      InvalidateRect(hwnd,NULL,TRUE); 
      break; 
  } 
} 
 
static void APIPRIVATE GetHitTestRect ( HWND hwnd, PCBBUTTON pCBB, LPRECT lpRC ) 
{ 
 
  if (GetWindowLong(hwnd,GWL_STYLE) & CBBS_NOAUTOSIZE) 
    GetClientRect(hwnd,lpRC); 
  else 
  { 
    memcpy(lpRC,&pCBB->rcText,sizeof(RECT)); 
    if (((pCBB->rcButton.right-pCBB->rcButton.left)>0) && 
        ((pCBB->rcButton.bottom-pCBB->rcButton.top)>0)) 
    { 
      if (pCBB->rcButton.left < lpRC->left) 
        lpRC->left = pCBB->rcButton.left; 
      if (pCBB->rcButton.right > lpRC->right) 
        lpRC->right = pCBB->rcButton.right; 
      if (pCBB->rcButton.top < lpRC->top) 
        lpRC->top = pCBB->rcButton.top; 
      if (pCBB->rcButton.bottom > lpRC->bottom) 
        lpRC->bottom = pCBB->rcButton.bottom; 
    } 
  } 
} 
 
static void APIPRIVATE CheckNeedRepaint ( HWND hwnd, PCBBUTTON pCBB ) 
{ 
  int       iState = ITEMSTATE_COLD; 
  RECT      rcClient; 
  POINT     pt; 
 
  if (!pCBB->bEnabled) 
    iState = ITEMSTATE_DISABLED; 
  else 
  { 
    GetHitTestRect(hwnd,pCBB,&rcClient); 
 
    if (pCBB->bKeyDown) 
      iState = ITEMSTATE_PRESSED; 
    else 
    { 
      pt.x = pCBB->iMouseX; 
      pt.y = pCBB->iMouseY; 
      if (PtInRect(&rcClient,pt)) 
      { 
        if (pCBB->bLButtonDown) 
          iState = ITEMSTATE_PRESSED; 
        else 
          iState = ITEMSTATE_HOT; 
      } 
      else 
      if (GetCapture()==hwnd) 
        iState = ITEMSTATE_HOT; 
    } 
  } 
 
  if (pCBB->iState!=iState) 
  { 
    pCBB->iState = iState; 
    InvalidateRect(hwnd,NULL,TRUE); 
  } 
} 
 
// iRequiredWidth only used if !(lStyle & TLS_NOAUTOSIZE) !!! 
static BOOL APIENTRY GetItemSize ( HWND hwnd, PCBBUTTON pCBB, PSIZE pSI, int iRequiredWidth ) 
{ 
  SIZE              siText,siSingleLine; 
  TCHAR             szText[256]; 
  HDC               hDC; 
  HGDIOBJ           hOldObj; 
  RECT              rcClient,rcText,rcClientOrig; 
  LONG              lStyle   = GetWindowLong(hwnd,GWL_STYLE); 
  LONG              lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); 
  UINT              uDTStyle = 0L; 
  int               iTextWidth,iTextHeight,iDelta; 
  int               iPreTextWidth,iPreTextHeight; 
  UINT              uAlign; 
  SIZE              siTheme; 
  BOOL              bIsPushButton = FALSE; 
 
  if (!pCBB) return FALSE; 
 
  if (((lStyle & CBBS_TYPEMASK)==CBBS_PUSHBUTTON) || 
      ((lStyle & CBBS_TYPEMASK)==CBBS_DEFPUSHBUTTON)) 
  { 
    uAlign = BUTTON_CENTER; 
    bIsPushButton = TRUE; 
  } 
  else 
    uAlign = BUTTON_LEFT; 
 
  if (lStyle & CBBS_LEFT) 
    uAlign = BUTTON_LEFT; 
  else 
  { 
    if (lStyle & CBBS_RIGHT) 
      uAlign = BUTTON_RIGHT; 
    else 
    if (lStyle & CBBS_CENTER) 
      uAlign = BUTTON_CENTER; 
  } 
 
  if (lExStyle & WS_EX_RIGHT) 
  { 
    lStyle |= CBBS_LEFTTEXT; 
    if (uAlign==BUTTON_LEFT) 
      uAlign=BUTTON_RIGHT; 
    else 
    if (uAlign==BUTTON_RIGHT) 
      uAlign=BUTTON_LEFT; 
  } 
 
  if (lStyle & CBBS_NOAUTOSIZE) 
  { 
    GetClientRect(hwnd,&rcClient); 
    pSI->cx = rcClient.right; 
    pSI->cy = rcClient.bottom; 
  } 
  else 
  { 
    if (iRequiredWidth==-1) 
      GetClientRect(hwnd,&rcClient); 
    else 
      rcClient.right  = iRequiredWidth; 
    rcClient.left     = rcClient.top = 0; 
    rcClient.bottom   = 32767; 
  } 
  memcpy(&rcClientOrig,&rcClient,sizeof(RECT)); 
  memset(&pCBB->rcText,0,sizeof(RECT)); 
  memset(&pCBB->rcButton,0,sizeof(RECT)); 
 
  hDC = GetDC(hwnd); 
  if (hDC) 
  { 
    if (bIsPushButton) 
      hOldObj = SelectObject(hDC,pCBB->hFontNormal); 
    else 
      hOldObj = SelectObject(hDC,pCBB->hFontCheckedHot); 
 
    szText[0]=0x00; 
    GetWindowText(hwnd,szText,256); 
 
    rcText.left     =  
    rcText.right    =  
    rcText.top      =  
    rcText.bottom   = 0; 
    uDTStyle        = DT_SINGLELINE|DT_NOCLIP|DT_CALCRECT|DT_LEFT|DT_TOP; 
    if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; 
    siSingleLine.cy = DrawTextEx(hDC,szText,lstrlen(szText),&rcText,uDTStyle,NULL); 
    siSingleLine.cx = rcText.right; 
 
    // Calculate button and text dimensions 
 
    switch(lStyle & CBBS_TYPEMASK) 
    { 
      case CBBS_PUSHBUTTON: 
      case CBBS_DEFPUSHBUTTON: 
        GetClientRect(hwnd,&rcClient); 
        pSI->cx = rcClient.right; 
        pSI->cy = rcClient.bottom; 
        pCBB->rcButton.right  = rcClient.right; 
        pCBB->rcButton.bottom = rcClient.bottom; 
 
        pCBB->rcText.left     = BUTTON_HSPACE; 
        pCBB->rcText.top      = BUTTON_VSPACE1; 
        pCBB->rcText.right    = rcClient.right-(BUTTON_HSPACE<<1); 
        pCBB->rcText.bottom   = rcClient.bottom-(BUTTON_VSPACE1+BUTTON_VSPACE2); 
        break; 
 
      case CBBS_CHECKBOX: 
      case CBBS_AUTOCHECKBOX: 
      case CBBS_3STATE: 
      case CBBS_AUTO3STATE: 
        if (g_sEBI.bPreXP) 
        { 
          if (lStyle & CBBS_LEFTTEXT) // button right 
          { 
            pCBB->rcButton.right  = rcClient.right; 
            pCBB->rcButton.left   = pCBB->rcButton.right-siSingleLine.cy; 
            pCBB->rcButton.bottom = siSingleLine.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.right    = pCBB->rcButton.left-CHECK_HSPACE; 
          } 
          else 
          { 
            pCBB->rcButton.right  = siSingleLine.cy; 
            pCBB->rcButton.bottom = siSingleLine.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.left     = pCBB->rcButton.right+CHECK_HSPACE; 
            pCBB->rcText.right    = rcClient.right; 
          } 
        } 
        else 
        { 
          siTheme.cx = siTheme.cy = 0; 
          GetThemePartSize(pCBB->hTheme,hDC,BP_CHECKBOX,CBS_CHECKEDNORMAL,NULL,TS_DRAW,&siTheme); 
 
          if (lStyle & CBBS_LEFTTEXT) // button right 
          { 
            pCBB->rcButton.right  = rcClient.right; 
            pCBB->rcButton.left   = pCBB->rcButton.right-siTheme.cx; 
            pCBB->rcButton.bottom = siTheme.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.right    = pCBB->rcButton.left-CHECK_HSPACE; 
          } 
          else 
          { 
            pCBB->rcButton.right  = siTheme.cx; 
            pCBB->rcButton.bottom = siTheme.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.left     = pCBB->rcButton.right+CHECK_HSPACE; 
            pCBB->rcText.right    = rcClient.right; 
          } 
 
          iDelta = siSingleLine.cy-siTheme.cy; 
 
          if (iDelta) // >0: text>button, <0: button>text 
          { 
            if (iDelta<0) // button>text 
            { 
              pCBB->rcText.top = (-iDelta)>>1; 
            } 
            else 
            { 
              iDelta>>=1; 
              pCBB->rcButton.top    += iDelta; 
              pCBB->rcButton.bottom += iDelta; 
            } 
          } 
        } 
        break; 
 
      case CBBS_RADIOBUTTON: 
      case CBBS_AUTORADIOBUTTON: 
        if (g_sEBI.bPreXP) 
        { 
          if (lStyle & CBBS_LEFTTEXT) // button right 
          { 
            pCBB->rcButton.right  = rcClient.right; 
            pCBB->rcButton.left   = pCBB->rcButton.right-siSingleLine.cy; 
            pCBB->rcButton.bottom = siSingleLine.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.right    = pCBB->rcButton.left-RADIO_HSPACE; 
          } 
          else 
          { 
            pCBB->rcButton.right  = siSingleLine.cy; 
            pCBB->rcButton.bottom = siSingleLine.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.left     = pCBB->rcButton.right+RADIO_HSPACE; 
            pCBB->rcText.right    = rcClient.right; 
          } 
        } 
        else 
        { 
          siTheme.cx = siTheme.cy = 0; 
          GetThemePartSize(pCBB->hTheme,hDC,BP_RADIOBUTTON,RBS_CHECKEDNORMAL,NULL,TS_DRAW,&siTheme); 
 
          if (lStyle & CBBS_LEFTTEXT) // button right 
          { 
            pCBB->rcButton.right  = rcClient.right; 
            pCBB->rcButton.left   = pCBB->rcButton.right-siTheme.cx; 
            pCBB->rcButton.bottom = siTheme.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.right    = pCBB->rcButton.left-RADIO_HSPACE; 
          } 
          else 
          { 
            pCBB->rcButton.right  = siTheme.cx; 
            pCBB->rcButton.bottom = siTheme.cy; 
 
            pCBB->rcText.bottom   = rcClient.bottom; 
            pCBB->rcText.left     = pCBB->rcButton.right+RADIO_HSPACE; 
            pCBB->rcText.right    = rcClient.right; 
          } 
 
          iDelta = siSingleLine.cy-siTheme.cy; 
 
          if (iDelta) // >0: text>button, <0: button>text 
          { 
            if (iDelta<0) // button>text 
            { 
              pCBB->rcText.top = (-iDelta)>>1; 
            } 
            else 
            { 
              iDelta>>=1; 
              pCBB->rcButton.top    += iDelta; 
              pCBB->rcButton.bottom += iDelta; 
            } 
          } 
        } 
        break; 
 
      default: 
        SelectObject(hDC,hOldObj); 
        ReleaseDC(hwnd,hDC); 
        return FALSE; 
    } 
 
    rcText.left   = 0; 
    rcText.right  = pCBB->rcText.right-pCBB->rcText.left; 
    rcText.top    = 0; 
    rcText.bottom = 32767; 
 
    if (lStyle & CBBS_FOCUSRECT) 
      rcText.right -= 2; 
 
    if (lStyle & CBBS_WORDBREAK)         // multiline, use current control width 
    { 
      uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; 
    } 
    else 
    { 
      if (lStyle & CBBS_END_ELLIPSIS)    // singleline, use current control width 
      { 
        uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; 
      } 
      else                              // singleline, ignore current control width 
      { 
        uDTStyle = DT_SINGLELINE|DT_NOCLIP; 
      } 
    } 
 
    uDTStyle |= DT_CALCRECT|DT_LEFT|DT_TOP; 
    if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; 
 
    siText.cy = DrawTextEx(hDC,szText,lstrlen(szText),&rcText,uDTStyle,NULL); 
    siText.cx = rcText.right; 
 
    pCBB->bMultiLine = (siText.cy>=(siSingleLine.cy<<1)) ? TRUE : FALSE; 
 
    iTextWidth  = siText.cx; 
    iTextHeight = siText.cy; 
 
    if (lStyle & CBBS_FOCUSRECT) 
    { 
      iTextWidth  += 2; 
      iTextHeight += 2; 
    } 
 
    if (bIsPushButton) 
    { 
      iPreTextWidth  = pCBB->rcText.right-pCBB->rcText.left; 
      iPreTextHeight = pCBB->rcText.bottom-pCBB->rcText.top; 
 
      if (iPreTextWidth>iTextWidth) 
      { 
        iDelta = iPreTextWidth-iTextWidth; 
        switch(uAlign) 
        { 
          case BUTTON_LEFT: 
            pCBB->rcText.right -= iDelta; 
            break; 
          case BUTTON_RIGHT: 
            pCBB->rcText.left  += iDelta; 
            break; 
          default: 
            pCBB->rcText.left  += (iDelta>>1); 
            pCBB->rcText.right -= iDelta-(iDelta>>1); 
        } 
      } 
      if (iPreTextHeight>iTextHeight) 
      { 
        iDelta = (iPreTextHeight-iTextHeight); 
        pCBB->rcText.top    += iDelta>>1; 
        pCBB->rcText.bottom -= iDelta-(iDelta>>1); 
      } 
      else 
      if (iPreTextHeightrcText.top    -= iDelta>>1; 
        pCBB->rcText.bottom += iDelta-(iDelta>>1); 
      } 
    } 
    else 
    { 
      if (lStyle & CBBS_FOCUSRECT) 
      { 
        pCBB->rcText.top --; 
        if (pCBB->rcText.top<0) 
        { 
          pCBB->rcText.top      ++; 
          pCBB->rcButton.top    ++; 
          pCBB->rcButton.bottom ++; 
        } 
      } 
      pCBB->rcText.bottom = pCBB->rcText.top + iTextHeight; 
 
      iPreTextWidth = pCBB->rcText.right-pCBB->rcText.left; 
      if (iPreTextWidth>iTextWidth) 
      { 
        iDelta = iPreTextWidth-iTextWidth; 
        switch(uAlign) 
        { 
          case BUTTON_LEFT: 
            pCBB->rcText.right -= iDelta; 
            break; 
          case BUTTON_RIGHT: 
            pCBB->rcText.left  += iDelta; 
            break; 
          default: 
            iDelta>>=1; 
            pCBB->rcText.left  += iDelta; 
            pCBB->rcText.right -= iDelta; 
        } 
      } 
    } 
 
    SelectObject(hDC,hOldObj); 
    ReleaseDC(hwnd,hDC); 
  } 
 
  if ((lStyle & CBBS_NOAUTOSIZE) || 
      ((lStyle & CBBS_TYPEMASK)==CBBS_PUSHBUTTON) || 
      ((lStyle & CBBS_TYPEMASK)==CBBS_DEFPUSHBUTTON)) 
    return TRUE; 
 
  // pSI füllen 
 
  memcpy(&rcText,&pCBB->rcText,sizeof(RECT)); 
  if (((pCBB->rcButton.right-pCBB->rcButton.left)>0) && 
      ((pCBB->rcButton.bottom-pCBB->rcButton.top)>0)) 
  { 
    if (pCBB->rcButton.left < rcText.left) 
      rcText.left = pCBB->rcButton.left; 
    if (pCBB->rcButton.right > rcText.right) 
      rcText.right = pCBB->rcButton.right; 
    if (pCBB->rcButton.top < rcText.top) 
      rcText.top = pCBB->rcButton.top; 
    if (pCBB->rcButton.bottom > rcText.bottom) 
      rcText.bottom = pCBB->rcButton.bottom; 
  } 
 
  pSI->cx = rcText.right/*-rcText.left*/; 
  pSI->cy = rcText.bottom/*-rcText.top*/; 
 
  return TRUE; 
} 
 
LRESULT CALLBACK CBButtonWndProc ( HWND     hwnd, 
                                   UINT     uMsg, 
                                   WPARAM   wParam, 
                                   LPARAM   lParam ) 
{ 
 
  switch(uMsg) 
  { 
    case WM_GETORIGDIMENSIONS: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (pCBB) 
        { 
          *((int*)wParam) = pCBB->iOrigWidth; 
          *((int*)lParam) = pCBB->iOrigHeight; 
        } 
        else 
        { 
          *((int*)wParam) = 0; 
          *((int*)lParam) = 0; 
        } 
        return 0L; 
      } 
 
    case WM_CREATE: 
      { 
        PCBBUTTON       pCBB = (PCBBUTTON)malloc(sizeof(CBBUTTON)); 
        LOGFONT         lf; 
        SIZE            si; 
 
        if (!pCBB) return -1L; 
        memset(pCBB,0,sizeof(CBBUTTON)); 
 
        { 
          RECT rcClient; 
          GetClientRect(hwnd,&rcClient); 
          pCBB->iOrigWidth  = rcClient.right; 
          pCBB->iOrigHeight = rcClient.bottom; 
        } 
 
        pCBB->cbSize = sizeof(CBBUTTON); 
 
        if (!g_sEBI.bPreXP) 
        { 
          pCBB->hTheme = OpenThemeData(hwnd,L"BUTTON"); 
          if (!pCBB->hTheme) 
          { 
            free(pCBB); 
            return -1L; 
          } 
        } 
 
        pCBB->bEnabled = IsWindowEnabled(hwnd); 
        pCBB->iMouseX  = -1; 
        pCBB->iMouseY  = -1; 
        pCBB->iState   = pCBB->bEnabled ? ITEMSTATE_COLD : ITEMSTATE_DISABLED; 
 
        if (GetLogFontEx((HFONT)GetStockObject(DEFAULT_GUI_FONT),&lf,&pCBB->uDescent)) 
        { 
          lf.lfWeight               = FW_NORMAL; 
          lf.lfItalic               = FALSE; 
          lf.lfUnderline            = FALSE; 
          pCBB->hFontNormal         = CreateFontIndirect(&lf); 
          lf.lfUnderline            = TRUE; 
          pCBB->hFontHot            = CreateFontIndirect(&lf); 
          lf.lfWeight               = FW_BOLD; 
          pCBB->hFontCheckedHot     = CreateFontIndirect(&lf); 
          lf.lfUnderline            = FALSE; 
          pCBB->hFontCheckedNormal  = CreateFontIndirect(&lf); 
        } 
 
        SetWindowLong(hwnd,GWL_USERDATA,(LONG)pCBB); 
 
        if (GetItemSize(hwnd,pCBB,&si,-1)) 
          SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); 
 
        return 0L; 
      } 
 
    case WM_ENABLE: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
 
        pCBB->bEnabled = wParam ? TRUE : FALSE; 
        pCBB->iState   = pCBB->bEnabled ? ITEMSTATE_COLD : ITEMSTATE_DISABLED; 
        InvalidateRect(hwnd,NULL,TRUE); 
        return 0L; 
      } 
 
    case WM_DESTROY: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if ((pCBB) && (pCBB->cbSize==sizeof(CBBUTTON))) 
        { 
          if (pCBB->hTheme) 
            CloseThemeData(pCBB->hTheme); 
          if (pCBB->hFontNormal) 
            DeleteObject(pCBB->hFontNormal); 
          if (pCBB->hFontHot) 
            DeleteObject(pCBB->hFontHot); 
          if (pCBB->hFontCheckedNormal) 
            DeleteObject(pCBB->hFontCheckedNormal); 
          if (pCBB->hFontCheckedHot) 
            DeleteObject(pCBB->hFontCheckedHot); 
          free(pCBB); 
          SetWindowLong(hwnd,GWL_USERDATA,(LONG)0L); 
        } 
        break; 
      } 
 
    case WM_THEMECHANGED: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (pCBB) 
        { 
          if (pCBB->hTheme) 
          { 
            CloseThemeData(pCBB->hTheme); 
            pCBB->hTheme = NULL; 
          } 
          if (!g_sEBI.bPreXP) 
            pCBB->hTheme = OpenThemeData(hwnd,L"BUTTON"); 
        } 
        return 0L; 
      } 
 
    case WM_SETFONT: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        LOGFONT   lf; 
        SIZE      si; 
 
        if (!pCBB) return 0L; 
 
        if (pCBB->hFontNormal) 
        { 
          DeleteObject(pCBB->hFontNormal); 
          pCBB->hFontNormal = NULL; 
        } 
        if (pCBB->hFontHot) 
        { 
          DeleteObject(pCBB->hFontHot); 
          pCBB->hFontHot = NULL; 
        } 
        if (pCBB->hFontCheckedNormal) 
        { 
          DeleteObject(pCBB->hFontCheckedNormal); 
          pCBB->hFontCheckedNormal = NULL; 
        } 
        if (pCBB->hFontCheckedHot) 
        { 
          DeleteObject(pCBB->hFontCheckedHot); 
          pCBB->hFontCheckedHot = NULL; 
        } 
 
        if (GetLogFontEx( wParam ? ((HFONT)wParam) : ((HFONT)GetStockObject(DEFAULT_GUI_FONT)),&lf,&pCBB->uDescent) ) 
        { 
          lf.lfWeight               = FW_NORMAL; 
          lf.lfItalic               = FALSE; 
          lf.lfUnderline            = FALSE; 
          pCBB->hFontNormal         = CreateFontIndirect(&lf); 
          lf.lfUnderline            = TRUE; 
          pCBB->hFontHot            = CreateFontIndirect(&lf); 
          lf.lfWeight               = FW_BOLD; 
          pCBB->hFontCheckedHot     = CreateFontIndirect(&lf); 
          lf.lfUnderline            = FALSE; 
          pCBB->hFontCheckedNormal  = CreateFontIndirect(&lf); 
 
          if (GetItemSize(hwnd,pCBB,&si,-1)) 
            SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); 
 
          if (LOWORD(lParam)) 
            InvalidateRect(hwnd,NULL,TRUE); 
        } 
        return 0L; 
      } 
 
    case CBBM_SETCURSOR: // wParam = HCURSOR(NULL=standard) 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return FALSE; 
        pCBB->hCursor = (HCURSOR)wParam; 
        return TRUE; 
      } 
 
    case WM_NCHITTEST: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        POINT     pt; 
        RECT      rcClient; 
 
        if (!pCBB) break; 
        GetHitTestRect(hwnd,pCBB,&rcClient); 
        pt.x = (int)((short)LOWORD(lParam)); 
        pt.y = (int)((short)HIWORD(lParam)); 
        ScreenToClient(hwnd,&pt); 
        if (PtInRect(&rcClient,pt)) 
          return HTCLIENT; 
        else 
          return HTNOWHERE; 
      } 
 
    case WM_SETCURSOR: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return FALSE; 
 
        if (LOWORD(lParam)==HTCLIENT) 
          SetCursor(pCBB->hCursor ? pCBB->hCursor : LoadCursor(NULL,IDC_ARROW)); 
        else 
          SetCursor(LoadCursor(NULL,IDC_ARROW)); 
 
        return TRUE; 
      } 
 
    case WM_ERASEBKGND: 
        return TRUE; 
 
    case WM_SIZE: 
    { 
      PCBBUTTON         pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
      SIZE              si; 
 
      if (!pCBB) return FALSE; 
 
      GetItemSize(hwnd,pCBB,&si,-1); 
      break; 
    } 
 
    case WM_CALCDIMENSIONS: // wParam = LPSIZE, lParam = width of control in px (-1 = get current width) 
      { 
        PCBBUTTON         pCBBSave,pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        BOOL              bReturn; 
 
        if (!pCBB) return FALSE; 
 
        if (IsBadWritePtr((VOID *)wParam,sizeof(SIZE))) 
          return FALSE; 
 
        pCBBSave = (PCBBUTTON)malloc(sizeof(CBBUTTON)); 
        if (!pCBBSave) return FALSE; 
        memcpy(pCBBSave,pCBB,sizeof(CBBUTTON)); 
        bReturn = GetItemSize(hwnd,pCBB,(PSIZE)wParam,(int)lParam); 
        memcpy(pCBB,pCBBSave,sizeof(CBBUTTON)); 
        return bReturn; 
      } 
 
    case WM_KEYDOWN: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
 
        if ((wParam==VK_SPACE) && (pCBB->bFocus) && (pCBB->bEnabled) && (GetCapture()!=hwnd)) 
        { 
          pCBB->bKeyDown = TRUE; 
          CheckNeedRepaint(hwnd,pCBB); 
        } 
        return 0L; 
      } 
 
    case WM_KEYUP: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
 
        if ((wParam==VK_SPACE) && (pCBB->bFocus) && (pCBB->bEnabled) && (pCBB->bKeyDown)) 
        { 
          pCBB->bKeyDown = FALSE; 
          CheckNeedRepaint(hwnd,pCBB); 
 
          if (pCBB->bEnabled) 
          { 
            HandleClick(hwnd,pCBB); 
            SendMessage(GetParent(hwnd), 
                        WM_COMMAND, 
                        MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)CBBN_CLICKED) ), 
                        (LPARAM)hwnd); 
          } 
        } 
        return 0L; 
      } 
 
    case WM_LBUTTONDBLCLK: 
      { 
        PCBBUTTON pCBB   = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        LONG      lStyle = GetWindowLong(hwnd,GWL_STYLE); 
 
        if (!pCBB) return 0L; 
        if (!pCBB->bEnabled) return 0L; 
 
        pCBB->iMouseX        = (int)((short)LOWORD(lParam)); 
        pCBB->iMouseY        = (int)((short)HIWORD(lParam)); 
        pCBB->bLButtonDown   = TRUE; 
        pCBB->bLButtonDblClk = TRUE; 
        if ((!(lStyle & CBBS_NOSETFOCUSONCLICK)) && (pCBB->bEnabled)) SetFocus(hwnd); 
        SetCapture(hwnd); 
        CheckNeedRepaint(hwnd,pCBB); 
        return 0L; 
      } 
 
    case WM_LBUTTONDOWN: 
      { 
        PCBBUTTON pCBB   = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        LONG      lStyle = GetWindowLong(hwnd,GWL_STYLE); 
 
        if (!pCBB) return 0L; 
        if (!pCBB->bEnabled) return 0L; 
 
        pCBB->iMouseX      = (int)((short)LOWORD(lParam)); 
        pCBB->iMouseY      = (int)((short)HIWORD(lParam)); 
        pCBB->bLButtonDown = TRUE; 
        if ((!(lStyle & CBBS_NOSETFOCUSONCLICK)) && (pCBB->bEnabled)) SetFocus(hwnd); 
        SetCapture(hwnd); 
        CheckNeedRepaint(hwnd,pCBB); 
        return 0L; 
      } 
 
    case WM_LBUTTONUP: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        RECT      rcClient; 
        POINT     pt; 
        UINT      uNotify; 
 
        if (!pCBB) return 0L; 
        if (!pCBB->bEnabled) return 0L; 
 
        pCBB->iMouseX = (int)((short)LOWORD(lParam)); 
        pCBB->iMouseY = (int)((short)HIWORD(lParam)); 
        if (pCBB->bLButtonDown) 
        { 
          pCBB->bLButtonDown = FALSE; 
          CheckNeedRepaint(hwnd,pCBB); 
 
          pt.x = pCBB->iMouseX; 
          pt.y = pCBB->iMouseY; 
          GetClientRect(hwnd,&rcClient); 
          if (PtInRect(&rcClient,pt)) 
          { 
            ReleaseCapture(); 
            if (pCBB->bEnabled) 
            { 
              if (pCBB->bLButtonDblClk) 
              { 
                uNotify = CBBN_DOUBLECLICKED; 
                pCBB->bLButtonDblClk = FALSE; 
              } 
              else 
                uNotify = CBBN_CLICKED; 
              HandleClick(hwnd,pCBB); 
              SendMessage(GetParent(hwnd), 
                          WM_COMMAND, 
                          MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)uNotify) ), 
                          (LPARAM)hwnd); 
            } 
          } 
          else 
            ReleaseCapture(); 
        } 
        return 0L; 
      } 
 
    case WM_MOUSELEAVE: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
 
        pCBB->iMouseX     = -1; 
        pCBB->iMouseY     = -1; 
        pCBB->bTrackMouse = FALSE; 
        CheckNeedRepaint(hwnd,pCBB); 
 
        if (GetWindowLong(hwnd,GWL_STYLE) & CBBS_NOTIFY) 
        { 
          NMBCHOTITEM         nmbchi; 
 
          nmbchi.hdr.hwndFrom = hwnd; 
          nmbchi.hdr.idFrom   = GetWindowLong(hwnd,GWL_ID); 
          nmbchi.hdr.code     = CBBN_HOTITEMCHANGE; 
          nmbchi.dwFlags      = HICF_LEAVING; 
          SendMessage(GetParent(hwnd),WM_NOTIFY,(WPARAM)nmbchi.hdr.idFrom,(LPARAM)&nmbchi); 
        } 
 
        return 0L; 
      } 
 
    case WM_MOUSEMOVE: 
      { 
        PCBBUTTON       pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        TRACKMOUSEEVENT tme; 
 
        if (!pCBB) return 0L; 
        if (!pCBB->bEnabled) return 0L; 
 
        if (!pCBB->bTrackMouse) 
        { 
          pCBB->bTrackMouse = TRUE; 
          tme.cbSize        = sizeof(TRACKMOUSEEVENT); 
          tme.dwFlags       = TME_LEAVE; 
          tme.dwHoverTime   = 0; 
          tme.hwndTrack     = hwnd; 
          TrackMouseEvent(&tme); 
 
          if (GetWindowLong(hwnd,GWL_STYLE) & CBBS_NOTIFY) 
          { 
            NMBCHOTITEM         nmbchi; 
 
            nmbchi.hdr.hwndFrom = hwnd; 
            nmbchi.hdr.idFrom   = GetWindowLong(hwnd,GWL_ID); 
            nmbchi.hdr.code     = CBBN_HOTITEMCHANGE; 
            nmbchi.dwFlags      = HICF_ENTERING; 
            SendMessage(GetParent(hwnd),WM_NOTIFY,(WPARAM)nmbchi.hdr.idFrom,(LPARAM)&nmbchi); 
          } 
        } 
 
        pCBB->iMouseX = (int)((short)LOWORD(lParam)); 
        pCBB->iMouseY = (int)((short)HIWORD(lParam)); 
        CheckNeedRepaint(hwnd,pCBB); 
 
        return 0L; 
      } 
 
    case WM_SETFOCUS: 
      { 
        PCBBUTTON pCBB   = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        LONG      lStyle = GetWindowLong(hwnd,GWL_STYLE); 
 
        if (!pCBB) break; 
 
        pCBB->bFocus = TRUE; 
 
        if (lStyle & CBBS_NOTIFY) 
        { 
          SendMessage(GetParent(hwnd), 
                      WM_COMMAND, 
                      MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)CBBN_SETFOCUS) ), 
                      (LPARAM)hwnd); 
        } 
 
        InvalidateRect(hwnd,NULL,TRUE); 
        return 0L; 
      } 
 
    case WM_KILLFOCUS: 
      { 
        PCBBUTTON pCBB   = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        LONG      lStyle = GetWindowLong(hwnd,GWL_STYLE); 
 
        if (!pCBB) break; 
 
        pCBB->bFocus   = FALSE; 
        pCBB->bKeyDown = FALSE; 
 
        if (lStyle & CBBS_NOTIFY) 
        { 
          SendMessage(GetParent(hwnd), 
                      WM_COMMAND, 
                      MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)CBBN_KILLFOCUS) ), 
                      (LPARAM)hwnd); 
        } 
 
        InvalidateRect(hwnd,NULL,TRUE); 
        return 0L; 
      } 
 
    case WM_CAPTURECHANGED: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
 
        pCBB->bLButtonDown   = FALSE; 
        pCBB->bLButtonDblClk = FALSE; 
        pCBB->bTrackMouse    = FALSE; 
        pCBB->iMouseX        = -1; 
        pCBB->iMouseY        = -1; 
        CheckNeedRepaint(hwnd,pCBB); 
 
        return 0L; 
      } 
 
    case BM_GETCHECK: 
    case CBBM_GETCHECK: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
 
        return pCBB->uButtonState&0x3L; 
      } 
 
    case BM_SETCHECK: 
    case CBBM_SETCHECK: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        UINT      uOldState; 
 
        if (!pCBB) return 0L; 
 
        uOldState = pCBB->uButtonState; 
        pCBB->uButtonState = (((UINT)wParam)&0x3L)|(uOldState&~3); 
 
        if (uOldState!=pCBB->uButtonState) 
          InvalidateRect(hwnd,NULL,TRUE); 
        return 0L; 
      } 
 
    case CBBM_GETSTATE: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        UINT      uState; 
 
        if (!pCBB) return 0L; 
 
        uState = pCBB->uButtonState; 
 
        if (pCBB->iState==ITEMSTATE_PRESSED) 
          uState |= CBBST_PUSHED; 
        if (pCBB->bFocus) 
          uState |= CBBST_FOCUS; 
 
        return uState; 
      } 
 
    case CBBM_SETSTATE: 
      { 
        PCBBUTTON pCBB   = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        LONG      lStyle = GetWindowLong(hwnd,GWL_STYLE); 
        POINT     pt; 
        RECT      rcClient; 
 
        if (!pCBB) return 0L; 
 
        if ((wParam) && (pCBB->iState!=ITEMSTATE_PRESSED)) 
        { 
          pCBB->iMouseX = 0; 
          pCBB->iMouseY = 0; 
          pCBB->bLButtonDown = TRUE; 
          if ((!(lStyle & CBBS_NOSETFOCUSONCLICK)) && (pCBB->bEnabled)) SetFocus(hwnd); 
          SetCapture(hwnd); 
          CheckNeedRepaint(hwnd,pCBB); 
        } 
        else 
        if ((!wParam) && (pCBB->iState==ITEMSTATE_PRESSED)) 
        { 
          pCBB->iMouseX = (int)((short)LOWORD(lParam)); 
          pCBB->iMouseY = (int)((short)HIWORD(lParam)); 
          if (pCBB->bLButtonDown) 
          { 
            pCBB->bLButtonDown = FALSE; 
            CheckNeedRepaint(hwnd,pCBB); 
 
            pt.x = 0; 
            pt.y = 0; 
            GetClientRect(hwnd,&rcClient); 
            if (PtInRect(&rcClient,pt)) 
            { 
              ReleaseCapture(); 
              if ((pCBB->bEnabled) && (pCBB->iState==ITEMSTATE_HOT)) 
              { 
                HandleClick(hwnd,pCBB); 
                SendMessage(GetParent(hwnd), 
                            WM_COMMAND, 
                            MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)CBBN_CLICKED) ), 
                            (LPARAM)hwnd); 
              } 
            } 
            else 
              ReleaseCapture(); 
          } 
        } 
        return 0L; 
      } 
 
    case CBBM_SETSTYLE: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
        SIZE      si; 
 
        if (!pCBB) return 0L; 
 
        SetWindowLong(hwnd,GWL_STYLE,(LONG)wParam); 
        if (GetItemSize(hwnd,pCBB,&si,-1)) 
          SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); 
 
        if (lParam) 
          InvalidateRect(hwnd,NULL,TRUE); 
 
        return 0L; 
      } 
 
    case CBBM_CLICK: 
      { 
        PCBBUTTON pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBB) return 0L; 
        HandleClick(hwnd,pCBB); 
        SendMessage(GetParent(hwnd), 
                    WM_COMMAND, 
                    MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)CBBN_CLICKED) ), 
                    (LPARAM)hwnd); 
        return 0L; 
      } 
 
    case WM_PAINT: 
      { 
        PAINTSTRUCT       ps; 
        HDC               hDC; 
        POINT             pt = {0,0}; 
 
        hDC = BeginPaint(hwnd,&ps); 
        if (hDC) 
        { 
          CBButtonPaintDC(hwnd,hDC,pt,TRUE,-1); 
          EndPaint(hwnd,&ps); 
        } 
        return 0L; 
      } 
 
    case WM_PRINTCLIENT: 
      { 
        HDC               hDC    = (HDC)wParam; 
        UINT              uFlags = (UINT)lParam; 
        POINT             pt = {0,0}; 
 
        if (hDC) 
        { 
          if (!((!IsWindowVisible(hwnd)) && (uFlags & PRF_CHECKVISIBLE))) 
            CBButtonPaintDC(hwnd,hDC,pt,uFlags & PRF_ERASEBKGND ? TRUE : FALSE,-1); 
          return TRUE; 
        } 
        return FALSE; 
      } 
 
    default: 
      break; 
  } 
 
  return DefWindowProc(hwnd,uMsg,wParam,lParam); 
} 
 
void APIENTRY CBButtonPaintDC ( HWND hwnd, HDC hDC, POINT ptOffset, BOOL bPaintBackground, int iCtrlWidth ) 
{ 
  PCBBUTTON     pCBB = (PCBBUTTON)GetWindowLong(hwnd,GWL_USERDATA); 
  CBBUTTON      CBBSave; 
  LONG          lStyle   = GetWindowLong(hwnd,GWL_STYLE); 
  LONG          lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); 
  UINT          uDTStyle = 0L; 
  UINT          uAlign; 
  BOOL          bIsPushButton = FALSE; 
  RECT          rcClient; 
  HBITMAP       hOldBitmap,hBitmapMem; 
  HDC           hDCMem; 
  HBRUSH        hBackBrush; 
  BOOL          bDefaultButton; 
  UINT          uState,uPreState; 
  int           iOldMode,iOldColor; 
  HFONT         hOldFont; 
  SIZE          siText; 
  RECT          rcText; 
  int           iDelta,iTextWidthAvail; 
  TCHAR         szText[256]; 
 
  if (pCBB) 
  { 
    if (iCtrlWidth!=-1) 
    { 
      SIZE si; 
      memcpy(&CBBSave,pCBB,sizeof(CBBUTTON)); 
      GetItemSize(hwnd,pCBB,&si,iCtrlWidth); 
      rcClient.left   = rcClient.top = 0; 
      rcClient.right  = si.cx; 
      rcClient.bottom = si.cy; 
    } 
    else 
      GetClientRect(hwnd,&rcClient); 
 
    if (((lStyle & CBBS_TYPEMASK)==CBBS_PUSHBUTTON) || 
        ((lStyle & CBBS_TYPEMASK)==CBBS_DEFPUSHBUTTON)) 
    { 
      uAlign = BUTTON_CENTER; 
      bIsPushButton = TRUE; 
    } 
    else 
      uAlign = BUTTON_LEFT; 
   
    if (lStyle & CBBS_LEFT) 
      uAlign = BUTTON_LEFT; 
    else 
    { 
      if (lStyle & CBBS_RIGHT) 
        uAlign = BUTTON_RIGHT; 
      else 
      if (lStyle & CBBS_CENTER) 
        uAlign = BUTTON_CENTER; 
    } 
 
    if (lExStyle & WS_EX_RIGHT) 
    { 
      lStyle |= CBBS_LEFTTEXT; 
      if (uAlign==BUTTON_LEFT) 
        uAlign=BUTTON_RIGHT; 
      else 
      if (uAlign==BUTTON_RIGHT) 
        uAlign=BUTTON_LEFT; 
    } 
 
    hDCMem     = CreateCompatibleDC(hDC); 
    hBitmapMem = CreateCompatibleBitmap(hDC,rcClient.right,rcClient.bottom); 
 
    if ((hDCMem) && (hBitmapMem)) 
    { 
      hOldBitmap=SelectObject(hDCMem,hBitmapMem); 
 
      if (bPaintBackground) 
      { 
        hBackBrush = (HBRUSH)SendMessage(GetParent(hwnd),WM_CTLCOLORBTN,(WPARAM)hDCMem,(LPARAM)hwnd); 
        if (((ULONG)(hBackBrush))>1) 
          FillRect(hDCMem,&rcClient,hBackBrush); 
      } 
      else 
        BitBlt(hDCMem,0,0,rcClient.right,rcClient.bottom,hDC,ptOffset.x,ptOffset.y,SRCCOPY); 
 
/*      hBackBrush = CreateSolidBrush(RGB(0xF0,0xE0,0xC0)); 
      FillRect(hDCMem,&rcClient,hBackBrush); 
      DeleteObject(hBackBrush);*/ 
 
      switch(lStyle & CBBS_TYPEMASK) 
      { 
        case CBBS_PUSHBUTTON: 
        case CBBS_DEFPUSHBUTTON: 
          bDefaultButton = (lStyle & CBBS_TYPEMASK)==CBBS_DEFPUSHBUTTON ? TRUE : FALSE; 
          if (pCBB->bFocus)  
            bDefaultButton = TRUE; 
          if (g_sEBI.bPreXP) 
          { 
            if (!pCBB->bEnabled) 
              DrawFrameControl( hDCMem, 
                                &pCBB->rcButton, 
                                DFC_BUTTON, 
                                DFCS_BUTTONPUSH| 
                                (lStyle & CBBS_FLAT ? DFCS_FLAT : 0)| 
                                DFCS_INACTIVE ); 
            else 
            { 
              memcpy(&rcText,&pCBB->rcButton,sizeof(RECT)); 
              if (bDefaultButton) 
              { 
                HPEN hOldPen,hPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DDKSHADOW)); 
 
                hOldPen = SelectObject(hDCMem,hPen); 
                MoveToEx(hDCMem,rcText.left,rcText.top,NULL); 
                LineTo(hDCMem,rcText.right-1,rcText.top); 
                LineTo(hDCMem,rcText.right-1,rcText.bottom-1); 
                LineTo(hDCMem,rcText.left,rcText.bottom-1); 
                LineTo(hDCMem,rcText.left,rcText.top-1); 
                SelectObject(hDCMem,hOldPen); 
                rcText.left   ++; 
                rcText.right  --; 
                rcText.top    ++; 
                rcText.bottom --; 
              } 
              DrawFrameControl( hDCMem, 
                                &rcText, 
                                DFC_BUTTON, 
                                DFCS_BUTTONPUSH| 
                                (lStyle & CBBS_FLAT ? DFCS_FLAT : 0)| 
                                (pCBB->iState==ITEMSTATE_PRESSED ? DFCS_PUSHED : 0) ); 
            } 
          } 
          else 
          if (pCBB->hTheme) 
          { 
            switch(pCBB->iState) 
            { 
              case ITEMSTATE_DISABLED: 
                uState = PBS_DISABLED; 
                break; 
              case ITEMSTATE_COLD: 
                uState = bDefaultButton ? PBS_DEFAULTED : PBS_NORMAL; 
                break; 
              case ITEMSTATE_PRESSED: 
                uState = PBS_PRESSED; 
                break; 
              case ITEMSTATE_HOT: 
                uState = PBS_HOT; 
                break; 
              default: 
                uState = PBS_NORMAL; 
                break; 
            } 
            DrawThemeBackground(pCBB->hTheme, 
                                hDCMem, 
                                BP_PUSHBUTTON, 
                                uState, 
                                &pCBB->rcButton, 
                                NULL); 
          } 
          break; 
 
        case CBBS_CHECKBOX: 
        case CBBS_AUTOCHECKBOX: 
          switch(pCBB->iState) 
          { 
            case ITEMSTATE_DISABLED: 
              uPreState = DFCS_BUTTONCHECK|DFCS_INACTIVE; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDDISABLED : CBS_UNCHECKEDDISABLED; 
              break; 
            case ITEMSTATE_COLD: 
              uPreState = DFCS_BUTTONCHECK; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDNORMAL : CBS_UNCHECKEDNORMAL; 
              break; 
            case ITEMSTATE_PRESSED: 
              uPreState = DFCS_BUTTONCHECK|DFCS_PUSHED; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDPRESSED : CBS_UNCHECKEDPRESSED; 
              break; 
            case ITEMSTATE_HOT: 
              uPreState = DFCS_BUTTONCHECK|DFCS_HOT; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDHOT : CBS_UNCHECKEDHOT; 
              break; 
          } 
          if (pCBB->uButtonState==CBBST_CHECKED) uPreState |= DFCS_CHECKED; 
          goto DoPaintCheck; 
        case CBBS_3STATE: 
        case CBBS_AUTO3STATE: 
          switch(pCBB->iState) 
          { 
            case ITEMSTATE_DISABLED: 
              uPreState = DFCS_BUTTON3STATE|DFCS_INACTIVE; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDDISABLED : (pCBB->uButtonState==CBBST_UNCHECKED ? CBS_UNCHECKEDDISABLED : CBS_MIXEDDISABLED); 
              break; 
            case ITEMSTATE_COLD: 
              uPreState = DFCS_BUTTON3STATE; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDNORMAL : (pCBB->uButtonState==CBBST_UNCHECKED ? CBS_UNCHECKEDNORMAL : CBS_MIXEDNORMAL); 
              break; 
            case ITEMSTATE_PRESSED: 
              uPreState = DFCS_BUTTON3STATE|DFCS_PUSHED; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDPRESSED : (pCBB->uButtonState==CBBST_UNCHECKED ? CBS_UNCHECKEDPRESSED : CBS_MIXEDPRESSED); 
              break; 
            case ITEMSTATE_HOT: 
              uPreState = DFCS_BUTTON3STATE|DFCS_HOT; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? CBS_CHECKEDHOT : (pCBB->uButtonState==CBBST_UNCHECKED ? CBS_UNCHECKEDHOT : CBS_MIXEDHOT); 
              break; 
          } 
          if (pCBB->uButtonState!=CBBST_UNCHECKED) uPreState |= DFCS_CHECKED; 
          if (pCBB->uButtonState==CBBST_INDETERMINATE) uPreState |= DFCS_INACTIVE; 
          DoPaintCheck: 
          if (lStyle & CBBS_FLAT) uPreState |= DFCS_FLAT; 
          if (g_sEBI.bPreXP) 
          { 
            DrawFrameControl( hDCMem, 
                              &pCBB->rcButton, 
                              DFC_BUTTON, 
                              uPreState ); 
          } 
          else 
          { 
            DrawThemeBackground(pCBB->hTheme, 
                                hDCMem, 
                                BP_CHECKBOX, 
                                uState, 
                                &pCBB->rcButton, 
                                NULL); 
          } 
          break; 
 
        case CBBS_RADIOBUTTON: 
        case CBBS_AUTORADIOBUTTON: 
          switch(pCBB->iState) 
          { 
            case ITEMSTATE_DISABLED: 
              uPreState = DFCS_BUTTONRADIO|DFCS_INACTIVE; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED; 
              break; 
            case ITEMSTATE_COLD: 
              uPreState = DFCS_BUTTONRADIO; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL; 
              break; 
            case ITEMSTATE_PRESSED: 
              uPreState = DFCS_BUTTONRADIO|DFCS_PUSHED; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED; 
              break; 
            case ITEMSTATE_HOT: 
              uPreState = DFCS_BUTTONRADIO|DFCS_HOT; 
              uState    = pCBB->uButtonState==CBBST_CHECKED ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT; 
              break; 
          } 
          if (pCBB->uButtonState==CBBST_CHECKED) uPreState |= DFCS_CHECKED; 
          if (lStyle & CBBS_FLAT) uPreState |= DFCS_FLAT; 
          if (g_sEBI.bPreXP) 
          { 
            DrawFrameControl( hDCMem, 
                              &pCBB->rcButton, 
                              DFC_BUTTON, 
                              uPreState ); 
          } 
          else 
          { 
            DrawThemeBackground(pCBB->hTheme, 
                                hDCMem, 
                                BP_RADIOBUTTON, 
                                uState, 
                                &pCBB->rcButton, 
                                NULL); 
          } 
          break; 
      } 
 
      // Print text 
 
      if (bIsPushButton) 
        hOldFont=SelectObject(hDCMem,pCBB->hFontNormal); 
      else 
      if (pCBB->uButtonState!=CBBST_UNCHECKED) 
      { 
        if ((pCBB->iState==ITEMSTATE_HOT) || (pCBB->iState==ITEMSTATE_PRESSED)) 
          hOldFont=SelectObject(hDCMem,pCBB->hFontCheckedHot); 
        else 
          hOldFont=SelectObject(hDCMem,pCBB->hFontCheckedNormal); 
      } 
      else 
      { 
        if ((pCBB->iState==ITEMSTATE_HOT) || (pCBB->iState==ITEMSTATE_PRESSED)) 
          hOldFont=SelectObject(hDCMem,pCBB->hFontHot); 
        else 
          hOldFont=SelectObject(hDCMem,pCBB->hFontNormal); 
      } 
 
      iOldMode = SetBkMode(hDCMem,TRANSPARENT); 
 
      if (pCBB->iState==ITEMSTATE_DISABLED) 
        iOldColor = SetTextColor(hDCMem,GetSysColor(COLOR_GRAYTEXT)); 
      else 
      { 
        if (bIsPushButton) 
          iOldColor = SetTextColor(hDCMem,GetSysColor(COLOR_BTNTEXT)); 
        else 
        { 
          if ((pCBB->iState==ITEMSTATE_HOT) || (pCBB->iState==ITEMSTATE_PRESSED)) 
            iOldColor = SetTextColor(hDCMem,GetSysColor(COLOR_HOTLIGHT)); 
          else 
            iOldColor = SetTextColor(hDCMem,GetSysColor(COLOR_BTNTEXT)); 
        } 
      } 
 
      szText[0]=0x00; 
      GetWindowText(hwnd,szText,256); 
 
      rcText.left   = 0; 
      rcText.right  = pCBB->rcText.right-pCBB->rcText.left; 
      rcText.top    = 0; 
      rcText.bottom = 32767; 
 
      if (lStyle & CBBS_FOCUSRECT) 
        rcText.right -= 2; 
 
      if (lStyle & CBBS_WORDBREAK)         // multiline, use current control width 
      { 
        uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; 
      } 
      else 
      { 
        if (lStyle & CBBS_END_ELLIPSIS)    // singleline, use current control width 
        { 
          uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; 
        } 
        else                              // singleline, ignore current control width 
        { 
          uDTStyle = DT_SINGLELINE|DT_NOCLIP; 
        } 
      } 
 
      uDTStyle |= DT_CALCRECT|DT_LEFT|DT_TOP; 
      if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; 
 
      siText.cy = DrawTextEx(hDCMem,szText,lstrlen(szText),&rcText,uDTStyle,NULL); 
      siText.cx = rcText.right; 
 
      if (lStyle & CBBS_FOCUSRECT) 
        siText.cx += 2; 
 
      uDTStyle &= ~(DT_CALCRECT|DT_LEFT|DT_NOCLIP); 
      memcpy(&rcText,&pCBB->rcText,sizeof(RECT)); 
      iTextWidthAvail = pCBB->rcText.right-pCBB->rcText.left; 
      if (siText.cx>1; 
            rcText.left  += iDelta; 
            rcText.right += iDelta; 
            break; 
        } 
      } 
 
      switch(uAlign) 
      { 
        case BUTTON_LEFT: 
          uDTStyle |= DT_LEFT; 
          break; 
        case BUTTON_RIGHT: 
          uDTStyle |= DT_RIGHT; 
          break; 
        case BUTTON_CENTER: 
          uDTStyle |= DT_CENTER; 
          break; 
      } 
 
      if (lStyle & CBBS_FOCUSRECT) 
      { 
        if (pCBB->bFocus) 
          DrawFocusRect(hDCMem,&rcText); 
        rcText.left   ++; 
        rcText.top    ++; 
        rcText.right  --; 
        rcText.bottom --; 
      } 
/* 
      if (bIsPushButton) 
      { 
        rcText.top    += pCBB->uDescent; 
        rcText.bottom += pCBB->uDescent; 
      } 
*/ 
      DrawTextEx(hDCMem,szText,lstrlen(szText),&rcText,uDTStyle,NULL); 
 
      SetBkMode(hDCMem,iOldMode); 
      SetTextColor(hDCMem,iOldColor); 
      BitBlt(hDC,ptOffset.x,ptOffset.y,rcClient.right,rcClient.bottom,hDCMem,0,0,SRCCOPY); 
      SelectObject(hDCMem,hOldBitmap); 
    } 
    if (hBitmapMem) DeleteObject(hBitmapMem); 
    if (hDCMem) DeleteDC(hDCMem); 
 
    if (iCtrlWidth!=-1) 
      memcpy(pCBB,&CBBSave,sizeof(CBBUTTON)); 
  } 
}