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)); }