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


/* 
 * file           : cbstatic.c 
 * language       : ANSI/ISO C 
 * plattform      : Win32 (Windows 98/Me/NT/2000/XP) 
 * description    : implements static control for xp-style explorer bar 
 * 
 * revision history: 
 * ================= 
 * 
 * date:       author:           description: 
 * -------------------------------------------------------------------------- 
 * 02/17/2004  Ingo A. Kubbilun  first published version 1.0 
 */ 
 
#include  
#include  
 
static BOOL APIPRIVATE GetItemSize ( HWND hwnd, PCBSTATIC pCBS, PSIZE pSI, int iRequiredWidth ) 
{ 
  TCHAR             szText[4096]; 
  int               iLength,iMaxWidth,iMaxHeight; 
  HDC               hDC; 
  HGDIOBJ           hOldObj; 
  RECT              rcClient,rcText; 
  LONG              lStyle   = GetWindowLong(hwnd,GWL_STYLE); 
  LONG              lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); 
  UINT              uDTStyle = 0L; 
 
  if (!pCBS) return FALSE; 
 
  pCBS->siText.cx = pCBS->siText.cy = 0; 
 
  if (lExStyle & WS_EX_RIGHT) 
  { 
    if ((lStyle & CBSS_HALIGNMASK)==CBSS_LEFT) 
      lStyle = (lStyle & ~CBSS_HALIGNMASK)|CBSS_RIGHT; 
    else 
    if ((lStyle & CBSS_HALIGNMASK)==CBSS_RIGHT) 
      lStyle = (lStyle & ~CBSS_HALIGNMASK)|CBSS_LEFT; 
  } 
 
  if (lStyle & CBSS_NOAUTOSIZE) 
  { 
    GetClientRect(hwnd,&rcClient); 
  } 
  else 
  { 
    if (iRequiredWidth==-1) 
      GetClientRect(hwnd,&rcClient); 
    else 
      rcClient.right  = iRequiredWidth; 
    rcClient.left     = rcClient.top = 0; 
    rcClient.bottom   = 32767; 
  } 
  iMaxWidth  = rcClient.right; 
  iMaxHeight = rcClient.bottom; 
 
  if ( (lStyle & CBSS_OWNERDRAW) && (!(lStyle & CBSS_NOAUTOSIZE)) ) 
  { 
    MEASUREITEMSTRUCT         mis; 
 
    mis.CtlID      = GetWindowLong(hwnd,GWL_ID); 
    mis.CtlType    = ODT_STATIC; 
    mis.itemID     = -1; 
    mis.itemWidth  = iMaxWidth; 
    mis.itemHeight = iMaxHeight; 
    mis.itemData   = (ULONG_PTR)pCBS->pvItemData; 
 
    if (SendMessage(GetParent(hwnd),WM_MEASUREITEM,(WPARAM)mis.CtlID,(LPARAM)&mis)) 
    { 
      iMaxWidth  = mis.itemWidth; 
      iMaxHeight = mis.itemHeight; 
    } 
  } 
 
  hDC = GetDC(hwnd); 
  if (hDC) 
  { 
    hOldObj = SelectObject(hDC,pCBS->hFont); 
 
    szText[0]=0x00; 
    iLength=GetWindowText(hwnd,szText,4096); 
     
    if (lStyle & CBSS_WORDWRAP)         // multiline, use current control width 
    { 
      rcText.left   = 0; 
      rcText.right  = rcClient.right; 
      rcText.top    = 0; 
      rcText.bottom = 0; 
 
      uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; 
 
      if (lStyle & CBSS_EDITCONTROL) 
        uDTStyle |= DT_EDITCONTROL; 
    } 
    else 
    { 
      if (lStyle & CBSS_END_ELLIPSIS)    // singleline, use current control width 
      { 
        rcText.left   = 0; 
        rcText.right  = rcClient.right; 
        rcText.top    = 0; 
        rcText.bottom = 0; 
        uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; 
      } 
      else 
      if (lStyle & CBSS_WORD_ELLIPSIS)    // singleline, use current control width 
      { 
        rcText.left   = 0; 
        rcText.right  = rcClient.right; 
        rcText.top    = 0; 
        rcText.bottom = 0; 
        uDTStyle = DT_WORD_ELLIPSIS|DT_SINGLELINE; 
      } 
      else 
      if (lStyle & CBSS_PATH_ELLIPSIS)    // singleline, use current control width 
      { 
        rcText.left   = 0; 
        rcText.right  = rcClient.right; 
        rcText.top    = 0; 
        rcText.bottom = 0; 
        uDTStyle = DT_PATH_ELLIPSIS|DT_SINGLELINE; 
      } 
      else                              // singleline, ignore current control width 
      { 
        rcText.left   = 0; 
        rcText.right  = 0; 
        rcText.top    = 0; 
        rcText.bottom = 0; 
        uDTStyle = DT_SINGLELINE|DT_NOCLIP; 
      } 
    } 
 
    uDTStyle |= DT_CALCRECT|DT_TOP|DT_LEFT;       // for calculation: always TOP & LEFT 
 
    if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; 
 
    if (lStyle & CBSS_NOPREFIX) 
      uDTStyle |= DT_NOPREFIX; 
 
    pCBS->siText.cy = DrawTextEx(hDC,szText,iLength,&rcText,uDTStyle,NULL); 
    pCBS->siText.cx = rcText.right; 
 
    SelectObject(hDC,hOldObj); 
    ReleaseDC(hwnd,hDC); 
  } 
 
  if (iMaxHeight==32767) 
    iMaxHeight = pCBS->siText.cy; 
 
  pSI->cx = iMaxWidth; 
  pSI->cy = iMaxHeight; 
  return TRUE; 
} 
 
LRESULT CALLBACK CBStaticWndProc ( HWND     hwnd, 
                                   UINT     uMsg, 
                                   WPARAM   wParam, 
                                   LPARAM   lParam ) 
{ 
 
  switch(uMsg) 
  { 
    case WM_GETORIGDIMENSIONS: 
      { 
        PCBSTATIC pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (pCBS) 
        { 
          *((int*)wParam) = pCBS->iOrigWidth; 
          *((int*)lParam) = pCBS->iOrigHeight; 
        } 
        else 
        { 
          *((int*)wParam) = 0; 
          *((int*)lParam) = 0; 
        } 
        return 0L; 
      } 
 
    case WM_CREATE: 
      { 
        PCBSTATIC         pCBS = (PCBSTATIC)malloc(sizeof(CBSTATIC)); 
        LOGFONT           lf; 
        LONG              lStyle = GetWindowLong(hwnd,GWL_STYLE); 
        SIZE              si; 
 
        if (!pCBS) return -1L; 
 
        memset(pCBS,0,sizeof(CBSTATIC)); 
 
        { 
          RECT rcClient; 
          GetClientRect(hwnd,&rcClient); 
          pCBS->iOrigWidth  = rcClient.right; 
          pCBS->iOrigHeight = rcClient.bottom; 
        } 
 
        pCBS->cbSize = sizeof(CBSTATIC); 
 
        pCBS->bEnabled = IsWindowEnabled(hwnd); 
 
        if (GetLogFont((HFONT)GetStockObject(DEFAULT_GUI_FONT),&lf)) 
        { 
          lf.lfWeight    = lStyle & CBSS_BOLD      ? FW_BOLD : FW_NORMAL; 
          lf.lfUnderline = lStyle & CBSS_UNDERLINE ? TRUE    : FALSE; 
          lf.lfItalic    = lStyle & CBSS_ITALIC    ? TRUE    : FALSE; 
          pCBS->hFont = CreateFontIndirect(&lf); 
        } 
 
        SetWindowLong(hwnd,GWL_USERDATA,(LONG)pCBS); 
 
        if (GetItemSize(hwnd,pCBS,&si,-1)) 
          SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); 
 
        return 0L; 
      } 
 
    case WM_DESTROY: 
      { 
        PCBSTATIC pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if ((pCBS) && (pCBS->cbSize==sizeof(CBSTATIC))) 
        { 
          if (pCBS->hFont) 
            DeleteObject(pCBS->hFont); 
          free(pCBS); 
          SetWindowLong(hwnd,GWL_USERDATA,(LONG)0L); 
        } 
        break; 
      } 
 
    case WM_SETFONT: 
      { 
        PCBSTATIC pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
        LOGFONT   lf; 
        LONG      lStyle = GetWindowLong(hwnd,GWL_STYLE); 
        SIZE      si; 
 
        if (!pCBS) return 0L; 
 
        if (pCBS->hFont) 
        { 
          DeleteObject(pCBS->hFont); 
          pCBS->hFont = NULL; 
        } 
 
        if (GetLogFont( wParam ? ((HFONT)wParam) : ((HFONT)GetStockObject(DEFAULT_GUI_FONT)),&lf) ) 
        { 
          lf.lfWeight    = lStyle & CBSS_BOLD      ? FW_BOLD : FW_NORMAL; 
          lf.lfUnderline = lStyle & CBSS_UNDERLINE ? TRUE    : FALSE; 
          lf.lfItalic    = lStyle & CBSS_ITALIC    ? TRUE    : FALSE; 
          pCBS->hFont    = CreateFontIndirect(&lf); 
 
          if (GetItemSize(hwnd,pCBS,&si,-1)) 
            SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); 
 
          if (LOWORD(lParam)) 
            InvalidateRect(hwnd,NULL,TRUE); 
        } 
        return 0L; 
      } 
 
    case WM_SIZE: 
    { 
      PCBSTATIC         pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
      SIZE              si; 
 
      if (!pCBS) return FALSE; 
 
      GetItemSize(hwnd,pCBS,&si,-1); 
      break; 
    } 
 
    case WM_CALCDIMENSIONS: // wParam = LPSIZE, lParam = width of control in px (-1 = get current width) 
      { 
        PCBSTATIC         pCBSSave,pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
        BOOL              bReturn; 
 
        if (!pCBS) return FALSE; 
 
        if (IsBadWritePtr((VOID *)wParam,sizeof(SIZE))) 
          return FALSE; 
 
        pCBSSave = (PCBSTATIC)malloc(sizeof(CBSTATIC)); 
        if (!pCBSSave) return FALSE; 
        memcpy(pCBSSave,pCBS,sizeof(CBSTATIC)); 
        bReturn = GetItemSize(hwnd,pCBS,(PSIZE)wParam,(int)lParam); 
        memcpy(pCBS,pCBSSave,sizeof(CBSTATIC)); 
        return bReturn; 
      } 
 
    case CBSM_SETITEMDATA:  // lParam = item data 
      { 
        PCBSTATIC         pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBS) return FALSE; 
 
        pCBS->pvItemData = (PVOID)lParam; 
 
        return TRUE; 
      } 
 
    case CBSM_GETITEMDATA: 
      { 
        PCBSTATIC         pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBS) return 0L; 
 
        return (LRESULT)pCBS->pvItemData; 
      } 
 
    case WM_ENABLE: 
      { 
        PCBSTATIC         pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
 
        if (!pCBS) return 0L; 
 
        pCBS->bEnabled = wParam ? TRUE : FALSE; 
 
        if (GetWindowLong(hwnd,GWL_STYLE) & CBSS_NOTIFY) 
          SendMessage(GetParent(hwnd),WM_COMMAND,MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)(pCBS->bEnabled ? CBSN_ENABLE : CBSN_DISABLE)) ),(LPARAM)hwnd); 
 
        InvalidateRect(hwnd,NULL,TRUE); 
        return 0L; 
      } 
 
    case WM_LBUTTONDOWN: 
      if (GetWindowLong(hwnd,GWL_STYLE) & CBSS_NOTIFY) 
        SendMessage(GetParent(hwnd),WM_COMMAND,MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)(CBSN_CLICKED)) ),(LPARAM)hwnd); 
      return 0L; 
 
    case WM_LBUTTONDBLCLK: 
      if (GetWindowLong(hwnd,GWL_STYLE) & CBSS_NOTIFY) 
        SendMessage(GetParent(hwnd),WM_COMMAND,MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), ((WORD)(CBSN_DBLCLK)) ),(LPARAM)hwnd); 
      return 0L; 
 
    case WM_PAINT: 
      { 
        PCBSTATIC         pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
        HDC               hDC; 
        PAINTSTRUCT       ps; 
        POINT             pt = {0,0}; 
 
        if (!pCBS) return 0L; 
 
        hDC = BeginPaint(hwnd,&ps); 
        if (hDC) 
          CBStatic32PaintDC(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))) 
            CBStatic32PaintDC(hwnd,hDC,pt,uFlags & PRF_ERASEBKGND ? TRUE : FALSE,-1); 
          return TRUE; 
        } 
        return FALSE; 
      } 
 
    default: 
      break; 
  } 
  return DefWindowProc(hwnd,uMsg,wParam,lParam); 
} 
 
void APIENTRY CBStatic32PaintDC ( HWND hwnd, HDC hDC, POINT ptOffset, BOOL bPaintBackground, int iCtrlWidth ) 
{ 
  PCBSTATIC         pCBS = (PCBSTATIC)GetWindowLong(hwnd,GWL_USERDATA); 
  CBSTATIC          CBSSave; 
  RECT              rcClient,rcText; 
  HBRUSH            hBackBrush = NULL; 
  LONG              lStyle = GetWindowLong(hwnd,GWL_STYLE); 
  LONG              lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); 
  HGDIOBJ           hOldObj; 
  TCHAR             szText[4096]; 
  int               iLength; 
  UINT              uDTStyle = 0L; 
  HDC               hDCMem; 
  HBITMAP           hOldBitmap,hBitmapMem; 
  int               iOldBkMode; 
 
  if (!pCBS) return; 
 
  if (iCtrlWidth!=-1) 
  { 
    SIZE si; 
    memcpy(&CBSSave,pCBS,sizeof(CBSTATIC)); 
    GetItemSize(hwnd,pCBS,&si,iCtrlWidth); 
    rcClient.left   = rcClient.top = 0; 
    rcClient.right  = si.cx; 
    rcClient.bottom = si.cy; 
  } 
  else 
    GetClientRect(hwnd,&rcClient); 
 
  hDCMem = CreateCompatibleDC(hDC); 
  hBitmapMem = CreateCompatibleBitmap(hDC,rcClient.right,rcClient.bottom); 
 
  if ((hDCMem) && (hBitmapMem)) 
  { 
    hOldBitmap = SelectObject(hDCMem,hBitmapMem); 
  
    if (lExStyle & WS_EX_RIGHT) 
    { 
      if ((lStyle & CBSS_HALIGNMASK)==CBSS_LEFT) 
        lStyle = (lStyle & ~CBSS_HALIGNMASK)|CBSS_RIGHT; 
      else 
      if ((lStyle & CBSS_HALIGNMASK)==CBSS_RIGHT) 
        lStyle = (lStyle & ~CBSS_HALIGNMASK)|CBSS_LEFT; 
    } 
 
    SetTextColor(hDCMem,pCBS->bEnabled ? GetSysColor(COLOR_BTNTEXT) : GetSysColor(COLOR_GRAYTEXT)); 
    SetBkColor(hDCMem,GetSysColor(COLOR_3DFACE)); 
 
    if (bPaintBackground) 
      hBackBrush = (HBRUSH)SendMessage(GetParent(hwnd),WM_CTLCOLORSTATIC,(WPARAM)hDCMem,(LPARAM)hwnd); 
    else 
      BitBlt(hDCMem,0,0,rcClient.right,rcClient.bottom,hDC,ptOffset.x,ptOffset.y,SRCCOPY); 
 
    if (lStyle & CBSS_OWNERDRAW) 
    { 
      DRAWITEMSTRUCT    dis; 
 
      dis.CtlID      = GetWindowLong(hwnd,GWL_ID); 
      dis.CtlType    = ODT_STATIC; 
      dis.itemID     = -1; 
      dis.itemAction = ODA_DRAWENTIRE; 
      dis.itemState  = pCBS->bEnabled ? 0 : ODS_DISABLED; 
      dis.hwndItem   = hwnd; 
      dis.hDC        = hDCMem; 
      memcpy(&dis.rcItem,&rcClient,sizeof(RECT)); 
      dis.itemData   = (ULONG_PTR)pCBS->pvItemData; 
      SendMessage(GetParent(hwnd),WM_DRAWITEM,(WPARAM)dis.CtlID,(LPARAM)&dis); 
    } 
    else 
    { 
      if (((ULONG)(hBackBrush))>1) 
        FillRect(hDCMem,&rcClient,hBackBrush); 
 
      hOldObj = SelectObject(hDCMem,pCBS->hFont); 
 
      szText[0]=0x00; 
      iLength=GetWindowText(hwnd,szText,4096); 
     
      if (lStyle & CBSS_WORDWRAP)         // multiline, use current control width 
      { 
        uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; 
        if (lStyle & CBSS_EDITCONTROL) 
          uDTStyle |= DT_EDITCONTROL; 
      } 
      else 
      { 
        if (lStyle & CBSS_END_ELLIPSIS)    // singleline, use current control width 
        { 
          uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; 
        } 
        else 
        if (lStyle & CBSS_WORD_ELLIPSIS)    // singleline, use current control width 
        { 
          uDTStyle = DT_WORD_ELLIPSIS|DT_SINGLELINE; 
        } 
        else 
        if (lStyle & CBSS_PATH_ELLIPSIS)    // singleline, use current control width 
        { 
          uDTStyle = DT_PATH_ELLIPSIS|DT_SINGLELINE; 
        } 
        else                              // singleline, ignore current control width 
        { 
          uDTStyle = DT_SINGLELINE|DT_NOCLIP; 
        } 
      } 
 
      if ((lStyle & CBSS_HALIGNMASK)==CBSS_CENTER) 
      { 
        uDTStyle    |= DT_CENTER; 
        rcText.left  = rcClient.left+(((rcClient.right-rcClient.left)-pCBS->siText.cx)>>1); 
        rcText.right = rcText.left+pCBS->siText.cx; 
      } 
      else 
      if ((lStyle & CBSS_HALIGNMASK)==CBSS_LEFT) 
      { 
        uDTStyle    |= DT_LEFT; 
        rcText.left  = rcClient.left; 
        rcText.right = rcText.left+pCBS->siText.cx; 
      } 
      else 
      if ((lStyle & CBSS_HALIGNMASK)==CBSS_RIGHT) 
      { 
        uDTStyle    |= DT_RIGHT; 
        rcText.right = rcClient.right; 
        rcText.left  = rcText.right-pCBS->siText.cx; 
      } 
 
      if ((lStyle & CBSS_VALIGNMASK)==CBSS_MIDDLE) 
      { 
        uDTStyle     |= DT_VCENTER; 
        rcText.top    = rcClient.top+(((rcClient.bottom-rcClient.top)-pCBS->siText.cy)>>1); 
        rcText.bottom = rcText.top+pCBS->siText.cy; 
      } 
      else 
      if ((lStyle & CBSS_VALIGNMASK)==CBSS_TOP) 
      { 
        uDTStyle     |= DT_TOP; 
        rcText.top    = rcClient.top; 
        rcText.bottom = rcText.top+pCBS->siText.cy; 
      } 
      else 
      if ((lStyle & CBSS_VALIGNMASK)==CBSS_BOTTOM) 
      { 
        uDTStyle     |= DT_BOTTOM; 
        rcText.bottom = rcClient.bottom; 
        rcText.top    = rcText.bottom-pCBS->siText.cy; 
      } 
 
      if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; 
 
      if (lStyle & CBSS_NOPREFIX) 
        uDTStyle |= DT_NOPREFIX; 
 
      iOldBkMode = SetBkMode(hDCMem,TRANSPARENT); 
      DrawTextEx(hDCMem,szText,iLength,&rcText,uDTStyle,NULL); 
      SetBkMode(hDCMem,iOldBkMode); 
 
      SelectObject(hDCMem,hOldObj); 
    } 
    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(pCBS,&CBSSave,sizeof(CBSTATIC)); 
}