www.pudn.com > ExpBar_src.zip > colheader.c
/* * file : colheader.c * language : ANSI/ISO C * plattform : Win32 (Windows 98/Me/NT/2000/XP) * description : implements collapsible header for the xp-style explorer bar * * revision history: * ================= * * date: author: description: * -------------------------------------------------------------------------- * 02/17/2004 Ingo A. Kubbilun first published version 1.0 */ #include#include #include #define CHS_NOAUTOSIZE CHS_reserved #define ISRECT(_r) ((((_r).right-(_r).left)>0) && (((_r).bottom-(_r).top)>0)) static void APIPRIVATE AlphaBlendHeaderBitmap ( HDC hDC, HDC hDCMem, HBITMAP hBitmap, LPRECT lpRC, int iBmpWidth, int iBmpHeight ); static void APIPRIVATE GetHitTestRect ( HWND hwnd, PCHSTRUCT pCHS, LPRECT lpRC ) { if (GetWindowLong(hwnd,GWL_STYLE) & CHS_NOAUTOSIZE) GetClientRect(hwnd,lpRC); else { memcpy(lpRC,&pCHS->rcBackground,sizeof(RECT)); } } static BOOL APIPRIVATE HitTest ( HWND hwnd, PCHSTRUCT pCHS, POINT pt ) { RECT rc; if (GetWindowLong(hwnd,GWL_STYLE) & CHS_NOAUTOSIZE) { GetClientRect(hwnd,&rc); return PtInRect(&rc,pt); } else { if (PtInRect(&pCHS->rcBackground,pt)) return TRUE; return PtInRect(&pCHS->rcIcon,pt); } } static void APIPRIVATE ResizeTTControl ( HWND hwnd, PCHSTRUCT pCHS ) { TOOLINFO ti; if ((pCHS) && (CH_HAVE_TOOLTIP_SAFE(pCHS))) { memset(&ti,0,sizeof(ti)); ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_TRANSPARENT; ti.hwnd = hwnd; ti.lpszText = LPSTR_TEXTCALLBACK; ti.uId = 1; GetHitTestRect(hwnd,pCHS,&ti.rect); SendMessage(pCHS->hwndToolTip,TTM_DELTOOL,0,(LPARAM)&ti); SendMessage(pCHS->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti); } } static void APIPRIVATE CheckNeedRepaint ( HWND hwnd, PCHSTRUCT pCHS ) { int iState = ITEMSTATE_COLD; POINT pt; if (!pCHS->bEnabled) iState = ITEMSTATE_DISABLED; else { if (pCHS->bKeyDown) iState = ITEMSTATE_PRESSED; else { pt.x = pCHS->iMouseX; pt.y = pCHS->iMouseY; if (HitTest(hwnd,pCHS,pt)) { if (pCHS->bLButtonDown) iState = ITEMSTATE_PRESSED; else iState = ITEMSTATE_HOT; } else if (GetCapture()==hwnd) iState = ITEMSTATE_HOT; } } if (pCHS->iState!=iState) { pCHS->iState = iState; InvalidateRect(hwnd,NULL,TRUE); } } // iRequiredWidth only used if !(lStyle & CHS_NOAUTOSIZE) !!! static BOOL APIENTRY GetItemSize ( HWND hwnd, PCHSTRUCT pCHS, PSIZE pSI, int iRequiredWidth ) { LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); LONG lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); UINT uAlign = pCHS->chf.uAlign; RECT rcClient,rcText; SIZE si; int iDelta,iArrHeight,iTextHeight,iTextWidth,iSingleTextHeight; HDC hDC; HGDIOBJ hOldObj; TCHAR szText[256]; SIZE siText,siSingleLine; UINT uDTStyle; si.cx = si.cy = 0; if (lExStyle & WS_EX_RIGHT) { if (uAlign==CH_LEFT) uAlign=CH_RIGHT; else if (uAlign==CH_RIGHT) uAlign=CH_LEFT; } if (lStyle & CHS_NOAUTOSIZE) { GetClientRect(hwnd,&rcClient); pSI->cx = rcClient.right-rcClient.left; pSI->cy = rcClient.bottom-rcClient.top; } else { if (iRequiredWidth==-1) GetClientRect(hwnd,&rcClient); else rcClient.right = iRequiredWidth; rcClient.left = rcClient.top = 0; rcClient.bottom = 32767; } memcpy(&pCHS->rcBackground,&rcClient,sizeof(RECT)); // Calculate icon rect (if any) memset(&pCHS->rcIcon,0,sizeof(RECT)); if ((lStyle & CHS_PANEHEADER) && (pCHS->chf.hIList)) { if (ImageList_GetIconSize(pCHS->chf.hIList,&si.cx,&si.cy)) { pCHS->rcIcon.left = rcClient.left+2; pCHS->rcIcon.top = rcClient.top; pCHS->rcIcon.right = pCHS->rcIcon.left+si.cx; pCHS->rcIcon.bottom = pCHS->rcIcon.top+si.cy; } } if (si.cx) rcClient.left = pCHS->rcIcon.right; if ((!pCHS->chf.hIList) && (pCHS->iLeftMargin)) rcClient.left += pCHS->iLeftMargin; else rcClient.left += ((int)pCHS->chf.uBorderLeft); rcClient.right -= ((int)pCHS->chf.uBorderRight); memset(&pCHS->rcButton,0,sizeof(RECT)); memset(&pCHS->rcText,0,sizeof(RECT)); // Calculate button rect if (lStyle & CHS_PANEHEADER) { if (lStyle & CHS_SPECIALGROUP) // special pane header { pCHS->rcButton.right = rcClient.right; pCHS->rcButton.left = pCHS->rcButton.right-g_sEBI.headerspecial.iBmpArrowWidth; iArrHeight = g_sEBI.headerspecial.iBmpArrowHeight; } else // normal pane header { pCHS->rcButton.right = rcClient.right; pCHS->rcButton.left = pCHS->rcButton.right-g_sEBI.headernormal.iBmpArrowWidth; iArrHeight = g_sEBI.headernormal.iBmpArrowHeight; } } else // group header { if (g_sEBI.bPreXP) { pCHS->rcButton.right = rcClient.right; pCHS->rcButton.left = pCHS->rcButton.right-g_sEBI.iBmpPreXPArrowWidth; iArrHeight = g_sEBI.iBmpPreXPArrowHeight; } else { pCHS->rcButton.right = rcClient.right; pCHS->rcButton.left = pCHS->rcButton.right-g_sEBI.headernormal.iBmpArrowWidth; iArrHeight = g_sEBI.headernormal.iBmpArrowHeight; } } rcClient.right = pCHS->rcButton.left-pCHS->chf.uGap; hDC = GetDC(hwnd); if (hDC) { memset(&rcText,0,sizeof(RECT)); hOldObj = SelectObject(hDC,pCHS->hFontHot); szText[0]=0x00; GetWindowText(hwnd,szText,256); if (lStyle & CHS_WORDBREAK) // multiline, use current control width { rcText.left = 0; rcText.right = rcClient.right-rcClient.left; if (lStyle & CHS_FOCUSRECT) rcText.right -= 2; uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; } else { if (lStyle & CHS_END_ELLIPSIS) // singleline, use current control width { rcText.left = 0; rcText.right = rcClient.right-rcClient.left; if (lStyle & CHS_FOCUSRECT) rcText.right -= 2; uDTStyle = DT_END_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_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; 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; iTextHeight = siText.cy; iSingleTextHeight = siSingleLine.cy; if (lStyle & CHS_FOCUSRECT) { iTextHeight += 2; iSingleTextHeight += 2; } pCHS->rcButton.top = pCHS->rcText.top = (int)pCHS->chf.uBorderTop; pCHS->rcText.bottom = pCHS->rcText.top+iTextHeight; pCHS->rcButton.bottom = pCHS->rcButton.top+iArrHeight; pCHS->bMultiLine = (siText.cy>=(siSingleLine.cy<<1)) ? TRUE : FALSE; if (!pCHS->bMultiLine) { if (iArrHeight>iSingleTextHeight) { iDelta = (iArrHeight-iSingleTextHeight)>>1; pCHS->rcText.top+=iDelta; pCHS->rcText.bottom+=iDelta; } } rcClient.bottom = pCHS->rcText.bottom>pCHS->rcButton.bottom ? pCHS->rcText.bottom : pCHS->rcButton.bottom; rcClient.bottom += (int)pCHS->chf.uBorderBottom; pCHS->rcBackground.bottom = rcClient.bottom; // horizontal alignment iTextWidth = siText.cx; if (lStyle & CHS_FOCUSRECT) iTextWidth += 2; switch(uAlign) { case CH_CENTER: iDelta = ((rcClient.right-rcClient.left)-iTextWidth)>>1; if (iDelta<0) iDelta=0; pCHS->rcText.left = rcClient.left+iDelta; pCHS->rcText.right = pCHS->rcText.left+iTextWidth; if (pCHS->rcText.right>rcClient.right) pCHS->rcText.right = rcClient.right; break; case CH_RIGHT: pCHS->rcText.right = rcClient.right; pCHS->rcText.left = pCHS->rcText.right-iTextWidth; if (pCHS->rcText.left rcText.left = rcClient.left; break; default: pCHS->rcText.left = rcClient.left; pCHS->rcText.right = pCHS->rcText.left+iTextWidth; if (pCHS->rcText.right>rcClient.right) pCHS->rcText.right = rcClient.right; break; } SelectObject(hDC,hOldObj); ReleaseDC(hwnd,hDC); } if (si.cy) { iDelta = si.cy-(rcClient.bottom-rcClient.top); if (iDelta>0) { rcClient.top += iDelta; rcClient.bottom += iDelta; pCHS->rcBackground.top += iDelta; pCHS->rcBackground.bottom += iDelta; pCHS->rcText.top += iDelta; pCHS->rcText.bottom += iDelta; pCHS->rcButton.top += iDelta; pCHS->rcButton.bottom += iDelta; } } ResizeTTControl(hwnd,pCHS); if (lStyle & CHS_NOAUTOSIZE) return TRUE; pSI->cx = pCHS->rcBackground.right; pSI->cy = pCHS->rcBackground.bottom; return TRUE; } LRESULT CALLBACK CollapsibleHeaderWndProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_LBUTTONDOWN: case WM_LBUTTONUP: if (CH_HAVE_DONTRELAYLBDNUP) break; case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MOUSEMOVE: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); MSG msg; if (!pCHS) break; if (CH_HAVE_TOOLTIP_SAFE(pCHS)) { msg.hwnd = hwnd; msg.message = uMsg; msg.wParam = wParam; msg.lParam = lParam; msg.pt.x = ((int)(short)LOWORD(lParam)); msg.pt.y = ((int)(short)HIWORD(lParam)); ClientToScreen(hwnd,&msg.pt); SendMessage(pCHS->hwndToolTip,TTM_RELAYEVENT,(WPARAM)0,(LPARAM)&msg); } break; } } switch(uMsg) { case WM_GETORIGDIMENSIONS: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (pCHS) { *((int*)wParam) = pCHS->iOrigWidth; *((int*)lParam) = pCHS->iOrigHeight; } else { *((int*)wParam) = 0; *((int*)lParam) = 0; } return 0L; } case WM_CREATE: { PCHSTRUCT pCHS = (PCHSTRUCT)malloc(sizeof(CHSTRUCT)); LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); LOGFONT lf; SIZE si; if (!pCHS) return -1L; memset(pCHS,0,sizeof(CHSTRUCT)); { RECT rcClient; GetClientRect(hwnd,&rcClient); pCHS->iOrigWidth = rcClient.right; pCHS->iOrigHeight = rcClient.bottom; } pCHS->cbSize = sizeof(CHSTRUCT); pCHS->iMouseX = -1; pCHS->iMouseY = -1; pCHS->bActive = TRUE; pCHS->bExpanded = lStyle & CHS_CREATEEXPANDED ? TRUE : FALSE; pCHS->bEnabled = IsWindowEnabled(hwnd); if (!pCHS->bEnabled) pCHS->iState = ITEMSTATE_DISABLED; else pCHS->iState = ITEMSTATE_COLD; if (CH_HAVE_TOOLTIP) { pCHS->hwndToolTip = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP|TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, NULL, NULL); if (!pCHS->hwndToolTip) { free(pCHS); return -1L; } SetWindowPos(pCHS->hwndToolTip,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); ResizeTTControl(hwnd,pCHS); } if (CH_HAVE_TOOLTIP_SAFE(pCHS)) SendMessage(pCHS->hwndToolTip,TTM_ACTIVATE,(WPARAM)((pCHS->bEnabled && pCHS->bActive) ? TRUE : FALSE),0L); pCHS->hLightPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DHILIGHT)); pCHS->hShadowPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DSHADOW)); memset(&lf,0,sizeof(LOGFONT)); if (lStyle & CHS_PANEHEADER) { if (lStyle & CHS_SPECIALGROUP) { pCHS->chf.cbSize = sizeof(CHFORMAT); pCHS->chf.iFontSize = g_sEBI.headerspecial.iFontSize; #ifdef UNICODE MultiByteToWideChar(CP_ACP,0,g_sEBI.headerspecial.szFontFace,-1,pCHS->chf.szFontFace,MAX_PATH); #else strcpy(pCHS->chf.szFontFace,g_sEBI.headerspecial.szFontFace); #endif pCHS->chf.iFWNormal = g_sEBI.headerspecial.iFontWeightHeader; pCHS->chf.iFWHot = g_sEBI.headerspecial.iFontWeightHeader; pCHS->chf.crNormal = g_sEBI.headerspecial.crHeaderNormal; pCHS->chf.crHot = g_sEBI.headerspecial.crHeaderHot; if (g_sEBI.headerspecial.uAlignment & TDA_CENTER) pCHS->chf.uAlign = CH_CENTER; else if (g_sEBI.headerspecial.uAlignment & TDA_RIGHT) pCHS->chf.uAlign = CH_RIGHT; else pCHS->chf.uAlign = CH_LEFT; pCHS->chf.uBorderTop = 1; pCHS->chf.uBorderBottom = 1; pCHS->chf.uBorderLeft = 4; pCHS->chf.uGap = 4; pCHS->chf.uBorderRight = 4; pCHS->chf.hCursor = LoadCursor(NULL,IDC_HAND); } else { pCHS->chf.cbSize = sizeof(CHFORMAT); pCHS->chf.iFontSize = g_sEBI.headernormal.iFontSize; #ifdef UNICODE MultiByteToWideChar(CP_ACP,0,g_sEBI.headernormal.szFontFace,-1,pCHS->chf.szFontFace,MAX_PATH); #else strcpy(pCHS->chf.szFontFace,g_sEBI.headernormal.szFontFace); #endif pCHS->chf.iFWNormal = g_sEBI.headernormal.iFontWeightHeader; pCHS->chf.iFWHot = g_sEBI.headernormal.iFontWeightHeader; pCHS->chf.crNormal = g_sEBI.headernormal.crHeaderNormal; pCHS->chf.crHot = g_sEBI.headernormal.crHeaderHot; if (g_sEBI.headernormal.uAlignment & TDA_CENTER) pCHS->chf.uAlign = CH_CENTER; else if (g_sEBI.headernormal.uAlignment & TDA_RIGHT) pCHS->chf.uAlign = CH_RIGHT; else pCHS->chf.uAlign = CH_LEFT; pCHS->chf.uBorderTop = 1; pCHS->chf.uBorderBottom = 1; pCHS->chf.uBorderLeft = 4; pCHS->chf.uGap = 4; pCHS->chf.uBorderRight = 4; pCHS->chf.hCursor = LoadCursor(NULL,IDC_HAND); } } else // group header { pCHS->chf.cbSize = sizeof(CHFORMAT); pCHS->chf.iFWNormal = FW_BOLD; pCHS->chf.iFWHot = FW_BOLD; pCHS->chf.crNormal = GetSysColor(COLOR_BTNTEXT); pCHS->chf.crHot = GetSysColor(COLOR_HOTLIGHT); pCHS->chf.uAlign = CH_LEFT; pCHS->chf.uGap = 4; pCHS->chf.hCursor = LoadCursor(NULL,IDC_HAND); GetLogFont(GetStockObject(DEFAULT_GUI_FONT),&lf); goto CreateFonts; } lf.lfHeight = pCHS->chf.iFontSize; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH; __strcpy(lf.lfFaceName,pCHS->chf.szFontFace); CreateFonts: lf.lfWeight = pCHS->chf.iFWNormal; lf.lfItalic = pCHS->chf.bItalicNormal; lf.lfUnderline = pCHS->chf.bULNormal; pCHS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = pCHS->chf.iFWHot; lf.lfItalic = pCHS->chf.bItalicHot; lf.lfUnderline = pCHS->chf.bULHot; pCHS->hFontHot = CreateFontIndirect(&lf); SetWindowLong(hwnd,GWL_USERDATA,(LONG)pCHS); if (GetItemSize(hwnd,pCHS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); ResizeTTControl(hwnd,pCHS); } return 0L; } case WM_DESTROY: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if ((pCHS) && (pCHS->cbSize==sizeof(CHSTRUCT))) { if (pCHS->hwndToolTip) DestroyWindow(pCHS->hwndToolTip); if (pCHS->hFontHot) DeleteObject(pCHS->hFontHot); if (pCHS->hFontNormal) DeleteObject(pCHS->hFontNormal); if (pCHS->hLightPen) DeleteObject(pCHS->hLightPen); if (pCHS->hShadowPen) DeleteObject(pCHS->hShadowPen); free(pCHS); SetWindowLong(hwnd,GWL_USERDATA,(LONG)0L); } break; } case WM_SETFONT: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); LOGFONT lf; SIZE si; LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); if ((!pCHS) || (lStyle & CHS_PANEHEADER)) return 0L; if (pCHS->hFontNormal) { DeleteObject(pCHS->hFontNormal); pCHS->hFontNormal = NULL; } if (pCHS->hFontHot) { DeleteObject(pCHS->hFontHot); pCHS->hFontHot = NULL; } if (GetLogFont( wParam ? ((HFONT)wParam) : ((HFONT)GetStockObject(DEFAULT_GUI_FONT)),&lf) ) { lf.lfWeight = pCHS->chf.iFWNormal; lf.lfItalic = pCHS->chf.bItalicNormal; lf.lfUnderline = pCHS->chf.bULNormal; pCHS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = pCHS->chf.iFWHot; lf.lfItalic = pCHS->chf.bItalicHot; lf.lfUnderline = pCHS->chf.bULHot; pCHS->hFontHot = CreateFontIndirect(&lf); if (GetItemSize(hwnd,pCHS,&si,-1)) { SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOREDRAW); ResizeTTControl(hwnd,pCHS); } if (LOWORD(lParam)) InvalidateRect(hwnd,NULL,TRUE); } return 0L; } case CHM_GETTTCTRL: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return (LPARAM)NULL; return (LPARAM)pCHS->hwndToolTip; } case CHM_SETSTATE: // wParam = (BOOL)bExpand, lParam = (BOOL)bRepaint { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; pCHS->bExpanded = (BOOL)wParam; if (CH_HAVE_PLAYSOUND) PlaySoundThemeSound( pCHS->bExpanded ? TEXT(".Default\\Maximize") : TEXT(".Default\\Minimize") ); if (lParam) InvalidateRect(hwnd,NULL,TRUE); return 0L; } case CHM_GETSTATE: // returns: (BOOL)bExpanded { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return FALSE; return pCHS->bExpanded; } case WM_NCHITTEST: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); POINT pt; if (!pCHS) break; pt.x = (int)((short)LOWORD(lParam)); pt.y = (int)((short)HIWORD(lParam)); ScreenToClient(hwnd,&pt); if (HitTest(hwnd,pCHS,pt)) return HTCLIENT; else return HTNOWHERE; } case WM_SETCURSOR: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return FALSE; if (!pCHS->bActive) break; if (LOWORD(lParam)==HTCLIENT) SetCursor(pCHS->chf.hCursor ? pCHS->chf.hCursor : LoadCursor(NULL,IDC_HAND)); else SetCursor(LoadCursor(NULL,IDC_ARROW)); return TRUE; } case WM_ERASEBKGND: return TRUE; case CHM_SETICON: // wParam = HIMAGELIST, lParam = idx { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (!pCHS) return FALSE; pCHS->chf.hIList = (HIMAGELIST)wParam; pCHS->chf.iIIdx = (int)lParam; if (GetItemSize(hwnd,pCHS,&si,-1)) SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); InvalidateRect(hwnd,NULL,TRUE); return TRUE; } case CHM_SETFORMAT: // lParam = pointer to memory with CHFORMAT structure { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); PCHFORMAT pCHF = (PCHFORMAT)lParam; LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); SIZE si; LOGFONT lf; if (!pCHS) return FALSE; if (IsBadReadPtr((LPCVOID)lParam,sizeof(CHFORMAT))) // return to original { if (lStyle & CHS_PANEHEADER) { pCHS->chf.uBorderTop = 1; pCHS->chf.uBorderBottom = 1; pCHS->chf.uBorderLeft = 4; pCHS->chf.uGap = 4; pCHS->chf.uBorderRight = 4; pCHS->chf.hCursor = LoadCursor(NULL,IDC_HAND); pCHS->chf.hIList = NULL; pCHS->chf.iIIdx = 0; } else { pCHS->chf.cbSize = sizeof(CHFORMAT); pCHS->chf.iFWNormal = FW_BOLD; pCHS->chf.iFWHot = FW_BOLD; pCHS->chf.crNormal = GetSysColor(COLOR_BTNTEXT); pCHS->chf.crHot = GetSysColor(COLOR_HOTLIGHT); pCHS->chf.uAlign = CH_LEFT; pCHS->chf.uBorderTop = 0; pCHS->chf.uBorderBottom = 0; pCHS->chf.uBorderLeft = 0; pCHS->chf.uGap = 4; pCHS->chf.uBorderRight = 0; pCHS->chf.hCursor = LoadCursor(NULL,IDC_HAND); GetLogFont(GetStockObject(DEFAULT_GUI_FONT),&lf); goto CreateFonts2; } goto DoUpdate; } if (pCHF->cbSize!=sizeof(CHFORMAT)) return FALSE; if (lStyle & CHS_PANEHEADER) { pCHS->chf.uBorderTop = pCHF->uBorderTop; pCHS->chf.uBorderBottom = pCHF->uBorderBottom; pCHS->chf.uBorderLeft = pCHF->uBorderLeft; pCHS->chf.uGap = pCHF->uGap; pCHS->chf.uBorderRight = pCHF->uBorderRight; pCHS->chf.hCursor = pCHF->hCursor; pCHS->chf.hIList = pCHF->hIList; pCHS->chf.iIIdx = pCHF->iIIdx; } else { memcpy(&pCHS->chf,pCHF,sizeof(CHFORMAT)); if (pCHS->hFontHot) DeleteObject(pCHS->hFontHot); if (pCHS->hFontNormal) DeleteObject(pCHS->hFontNormal); if (!pCHS->chf.iFontSize) { GetLogFont(GetStockObject(DEFAULT_GUI_FONT),&lf); goto CreateFonts2; } else { lf.lfHeight = pCHS->chf.iFontSize; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH; __strcpy(lf.lfFaceName,pCHS->chf.szFontFace); CreateFonts2: lf.lfWeight = pCHS->chf.iFWNormal; lf.lfItalic = pCHS->chf.bItalicNormal; lf.lfUnderline = pCHS->chf.bULNormal; pCHS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = pCHS->chf.iFWHot; lf.lfItalic = pCHS->chf.bItalicHot; lf.lfUnderline = pCHS->chf.bULHot; pCHS->hFontHot = CreateFontIndirect(&lf); } } DoUpdate: if (GetItemSize(hwnd,pCHS,&si,-1)) SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); InvalidateRect(hwnd,NULL,TRUE); return TRUE; } case CHM_GETFORMAT: // wParam = sizeof(CHFORMAT), lParam = pointer to memory to store CHFORMAT struct. { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return FALSE; if (wParam!=sizeof(CHFORMAT)) return FALSE; if (IsBadWritePtr((LPVOID)lParam,sizeof(CHFORMAT))) return FALSE; memcpy((LPVOID)lParam,&pCHS->chf,sizeof(CHFORMAT)); return TRUE; } case WM_THEMECHANGED: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); LOGFONT lf; LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); SIZE si; if (!pCHS) return 0L; memset(&lf,0,sizeof(LOGFONT)); if (lStyle & CHS_PANEHEADER) { if (lStyle & CHS_SPECIALGROUP) { pCHS->chf.iFontSize = g_sEBI.headerspecial.iFontSize; #ifdef UNICODE MultiByteToWideChar(CP_ACP,0,g_sEBI.headerspecial.szFontFace,-1,pCHS->chf.szFontFace,MAX_PATH); #else strcpy(pCHS->chf.szFontFace,g_sEBI.headerspecial.szFontFace); #endif pCHS->chf.iFWNormal = g_sEBI.headerspecial.iFontWeightHeader; pCHS->chf.iFWHot = g_sEBI.headerspecial.iFontWeightHeader; pCHS->chf.crNormal = g_sEBI.headerspecial.crHeaderNormal; pCHS->chf.crHot = g_sEBI.headerspecial.crHeaderHot; if (g_sEBI.headerspecial.uAlignment & TDA_CENTER) pCHS->chf.uAlign = CH_CENTER; else if (g_sEBI.headerspecial.uAlignment & TDA_RIGHT) pCHS->chf.uAlign = CH_RIGHT; else pCHS->chf.uAlign = CH_LEFT; } else { pCHS->chf.iFontSize = g_sEBI.headernormal.iFontSize; #ifdef UNICODE MultiByteToWideChar(CP_ACP,0,g_sEBI.headernormal.szFontFace,-1,pCHS->chf.szFontFace,MAX_PATH); #else strcpy(pCHS->chf.szFontFace,g_sEBI.headernormal.szFontFace); #endif pCHS->chf.iFWNormal = g_sEBI.headernormal.iFontWeightHeader; pCHS->chf.iFWHot = g_sEBI.headernormal.iFontWeightHeader; pCHS->chf.crNormal = g_sEBI.headernormal.crHeaderNormal; pCHS->chf.crHot = g_sEBI.headernormal.crHeaderHot; if (g_sEBI.headernormal.uAlignment & TDA_CENTER) pCHS->chf.uAlign = CH_CENTER; else if (g_sEBI.headernormal.uAlignment & TDA_RIGHT) pCHS->chf.uAlign = CH_RIGHT; else pCHS->chf.uAlign = CH_LEFT; } } else // group header { return 0L; } if (pCHS->hFontNormal) DeleteObject(pCHS->hFontNormal); if (pCHS->hFontHot) DeleteObject(pCHS->hFontHot); lf.lfHeight = pCHS->chf.iFontSize; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH; __strcpy(lf.lfFaceName,pCHS->chf.szFontFace); lf.lfWeight = pCHS->chf.iFWNormal; lf.lfItalic = pCHS->chf.bItalicNormal; lf.lfUnderline = pCHS->chf.bULNormal; pCHS->hFontNormal = CreateFontIndirect(&lf); lf.lfWeight = pCHS->chf.iFWHot; lf.lfItalic = pCHS->chf.bItalicHot; lf.lfUnderline = pCHS->chf.bULHot; pCHS->hFontHot = CreateFontIndirect(&lf); if (GetItemSize(hwnd,pCHS,&si,-1)) SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); InvalidateRect(hwnd,NULL,TRUE); return 0L; } case WM_SYSCOLORCHANGE: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); if (!pCHS) return 0L; if (pCHS->hLightPen) DeleteObject(pCHS->hLightPen); if (pCHS->hShadowPen) DeleteObject(pCHS->hShadowPen); pCHS->hLightPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DHILIGHT)); pCHS->hShadowPen = CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DSHADOW)); if ((!(lStyle & CHS_PANEHEADER)) && (!pCHS->bColorSet)) { pCHS->chf.crNormal = GetSysColor(COLOR_BTNTEXT); pCHS->chf.crHot = GetSysColor(COLOR_HOTLIGHT); } return 0L; } case WM_SIZE: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (!pCHS) return FALSE; GetItemSize(hwnd,pCHS,&si,-1); break; } case WM_CALCDIMENSIONS: // wParam = LPSIZE, lParam = width of control in px (-1 = get current width) { PCHSTRUCT pCHSSave,pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); BOOL bReturn; if (!pCHS) return FALSE; if (IsBadWritePtr((VOID *)wParam,sizeof(SIZE))) return FALSE; pCHSSave = (PCHSTRUCT)malloc(sizeof(CHSTRUCT)); if (!pCHSSave) return FALSE; memcpy(pCHSSave,pCHS,sizeof(CHSTRUCT)); bReturn = GetItemSize(hwnd,pCHS,(PSIZE)wParam,(int)lParam); memcpy(pCHS,pCHSSave,sizeof(CHSTRUCT)); return bReturn; } case WM_ENABLE: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; pCHS->bEnabled = (wParam ? TRUE : FALSE); CheckNeedRepaint(hwnd,pCHS); if (CH_HAVE_TOOLTIP_SAFE(pCHS)) SendMessage(pCHS->hwndToolTip,TTM_ACTIVATE,(WPARAM)((pCHS->bEnabled && pCHS->bActive) ? TRUE : FALSE),0L); return 0L; } case CHM_ACTIVATE: // wParam = BOOL { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; pCHS->bActive = (BOOL)wParam; if (!pCHS->bActive) { if (pCHS->bEnabled) { pCHS->iState = ITEMSTATE_COLD; pCHS->bLButtonDown = FALSE; pCHS->iMouseX = -1; pCHS->iMouseY = -1; InvalidateRect(hwnd,NULL,TRUE); } } if (CH_HAVE_TOOLTIP_SAFE(pCHS)) SendMessage(pCHS->hwndToolTip,TTM_ACTIVATE,(WPARAM)((pCHS->bEnabled && pCHS->bActive) ? TRUE : FALSE),0L); return 0L; } case WM_KEYDOWN: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; if ((wParam==VK_SPACE) && (pCHS->bFocus) && (pCHS->bEnabled) && (pCHS->bActive) && (GetCapture()!=hwnd)) { pCHS->bKeyDown = TRUE; CheckNeedRepaint(hwnd,pCHS); } return 0L; } case WM_KEYUP: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; if ((wParam==VK_SPACE) && (pCHS->bFocus) && (pCHS->bEnabled) && (pCHS->bActive) && (pCHS->bKeyDown)) { pCHS->bKeyDown = FALSE; CheckNeedRepaint(hwnd,pCHS); if (pCHS->bEnabled) { //NMHDR nmh; pCHS->bExpanded ^= TRUE; if (CH_HAVE_PLAYSOUND) PlaySoundThemeSound( pCHS->bExpanded ? TEXT(".Default\\Maximize") : TEXT(".Default\\Minimize") ); /* nmh.code = pCHS->bExpanded ? CHN_EXPANDED : CHN_COLLAPSED; nmh.hwndFrom = hwnd; nmh.idFrom = GetWindowLong(hwnd,GWL_ID); SendMessage(GetParent(hwnd),WM_NOTIFY,(WPARAM)hwnd,(LPARAM)&nmh); */ SendMessage(GetParent(hwnd), WM_COMMAND, MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), (WORD)(pCHS->bExpanded ? CHN_EXPANDED : CHN_COLLAPSED) ), (LPARAM)hwnd); } } return 0L; } case WM_LBUTTONDOWN: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; if ((!pCHS->bActive) || (!pCHS->bEnabled)) return 0L; pCHS->iMouseX = (int)((short)LOWORD(lParam)); pCHS->iMouseY = (int)((short)HIWORD(lParam)); pCHS->bLButtonDown = TRUE; if ((!CH_HAVE_NSFOC) && (pCHS->bEnabled)) SetFocus(hwnd); SetCapture(hwnd); CheckNeedRepaint(hwnd,pCHS); return 0L; } case WM_LBUTTONUP: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); RECT rcClient; POINT pt; if (!pCHS) return 0L; if ((!pCHS->bActive) || (!pCHS->bEnabled)) return 0L; pCHS->iMouseX = (int)((short)LOWORD(lParam)); pCHS->iMouseY = (int)((short)HIWORD(lParam)); if (pCHS->bLButtonDown) { pCHS->bLButtonDown = FALSE; CheckNeedRepaint(hwnd,pCHS); pt.x = pCHS->iMouseX; pt.y = pCHS->iMouseY; GetClientRect(hwnd,&rcClient); if (PtInRect(&rcClient,pt)) { ReleaseCapture(); if ((pCHS->bEnabled) /*&& (pCHS->iState==ITEMSTATE_HOT)*/) { // NMHDR nmh; pCHS->bExpanded ^= TRUE; if (CH_HAVE_PLAYSOUND) PlaySoundThemeSound( pCHS->bExpanded ? TEXT(".Default\\Maximize") : TEXT(".Default\\Minimize") ); /* nmh.code = pCHS->bExpanded ? CHN_EXPANDED : CHN_COLLAPSED; nmh.hwndFrom = hwnd; nmh.idFrom = GetWindowLong(hwnd,GWL_ID); SendMessage(GetParent(hwnd),WM_NOTIFY,(WPARAM)hwnd,(LPARAM)&nmh); */ SendMessage(GetParent(hwnd), WM_COMMAND, MAKELONG( ((WORD)GetWindowLong(hwnd,GWL_ID)), (WORD)(pCHS->bExpanded ? CHN_EXPANDED : CHN_COLLAPSED) ), (LPARAM)hwnd); } } else ReleaseCapture(); } return 0L; } case WM_MOUSELEAVE: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; pCHS->iMouseX = -1; pCHS->iMouseY = -1; pCHS->bTrackMouse = FALSE; CheckNeedRepaint(hwnd,pCHS); return 0L; } case WM_MOUSEMOVE: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); TRACKMOUSEEVENT tme; if (!pCHS) return 0L; if ((!pCHS->bActive) || (!pCHS->bEnabled)) return 0L; if (!pCHS->bTrackMouse) { pCHS->bTrackMouse = TRUE; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; tme.dwHoverTime = 0; tme.hwndTrack = hwnd; TrackMouseEvent(&tme); } pCHS->iMouseX = (int)((short)LOWORD(lParam)); pCHS->iMouseY = (int)((short)HIWORD(lParam)); CheckNeedRepaint(hwnd,pCHS); return 0L; } case WM_SETFOCUS: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) break; pCHS->bFocus = TRUE; if (CH_HAVE_FOCUSRECT) { InvalidateRect(hwnd,NULL,TRUE); return 0L; } else break; } case WM_KILLFOCUS: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) break; pCHS->bFocus = FALSE; pCHS->bKeyDown = FALSE; if (CH_HAVE_FOCUSRECT) { InvalidateRect(hwnd,NULL,TRUE); return 0L; } else break; } case WM_CAPTURECHANGED: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); if (!pCHS) return 0L; pCHS->bLButtonDown = FALSE; pCHS->bTrackMouse = FALSE; pCHS->iMouseX = -1; pCHS->iMouseY = -1; CheckNeedRepaint(hwnd,pCHS); return 0L; } case WM_NOTIFY: { int idCtrl = (int)wParam; LPNMHDR lpnmh = (LPNMHDR)lParam; PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); HWND hwndOrig; UINT idOrig; if (!pCHS) break; if ((lpnmh->hwndFrom==pCHS->hwndToolTip) && (lpnmh->code==TTN_GETDISPINFO)) { LPNMTTDISPINFO lpnmttdi = (LPNMTTDISPINFO)lParam; hwndOrig = lpnmh->hwndFrom; idOrig = lpnmh->idFrom; lpnmh->hwndFrom = hwnd; lpnmh->idFrom = GetWindowLong(hwnd,GWL_ID); lpnmh->code = CHN_GETDISPINFO; SendMessage(GetParent(hwnd),WM_NOTIFY,(WPARAM)hwnd,(LPARAM)lpnmh); lpnmh->hwndFrom = hwndOrig; lpnmh->idFrom = idOrig; lpnmh->code = TTN_GETDISPINFO; return 0L; } break; } case WM_PAINT: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); PAINTSTRUCT ps; HDC hDC; POINT pt = {0,0}; if (!pCHS) return 0L; hDC = BeginPaint(hwnd,&ps); if (hDC) ColHeaderPaintDC(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))) ColHeaderPaintDC(hwnd,hDC,pt,uFlags & PRF_ERASEBKGND ? TRUE : FALSE,-1); return TRUE; } return FALSE; } case CHM_SETLEFTMARGIN: { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); SIZE si; if (pCHS) { pCHS->iLeftMargin = (int)wParam; if (GetItemSize(hwnd,pCHS,&si,-1)) SetWindowPos(hwnd,NULL,0,0,si.cx,si.cy,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); return TRUE; } return FALSE; } default: break; } return DefWindowProc(hwnd,uMsg,wParam,lParam); } static void APIPRIVATE AlphaBlendHeaderBitmap ( HDC hDC, HDC hDCMem, HBITMAP hBitmap, LPRECT lpRC, int iBmpWidth, int iBmpHeight ) { BLENDFUNCTION bf; HBITMAP hOldBitmap; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 255; bf.AlphaFormat = AC_SRC_ALPHA; hOldBitmap = SelectObject(hDCMem,hBitmap); AlphaBlend(hDC,lpRC->left,lpRC->top, 2, lpRC->bottom-lpRC->top, hDCMem, 0, 0, 2, iBmpHeight,bf); AlphaBlend(hDC,lpRC->right-2,lpRC->top, 2, lpRC->bottom-lpRC->top, hDCMem, iBmpWidth-2, 0, 2, iBmpHeight,bf); AlphaBlend(hDC,lpRC->left+2,lpRC->top, lpRC->right-lpRC->left-4, lpRC->bottom-lpRC->top, hDCMem, 2, 0, iBmpWidth-4, iBmpHeight,bf); SelectObject(hDCMem,hOldBitmap); } void APIENTRY ColHeaderPaintDC ( HWND hwnd, HDC hDC, POINT ptOffset, BOOL bPaintBackground, int iCtrlWidth ) { PCHSTRUCT pCHS = (PCHSTRUCT)GetWindowLong(hwnd,GWL_USERDATA); CHSTRUCT CHSSave; HDC hDCMem; TCHAR szText[256]; HGDIOBJ hOldFont,hOldBitmap; int iOldColor,iOldBkMode,dy,idx,iArrWidth,iArrHeight; RECT rcText,rcClient; LONG lStyle = GetWindowLong(hwnd,GWL_STYLE); LONG lExStyle = GetWindowLong(hwnd,GWL_EXSTYLE); UINT uDTStyle = 0; UINT uAlign; BLENDFUNCTION bf; HBITMAP *phBitmap; HBRUSH hBrush; HBITMAP hBufferBitmap,hOldBufferBitmap; HDC hBufferDC; HPEN hOldPen; if (!pCHS) return; if (iCtrlWidth!=-1) { SIZE si; memcpy(&CHSSave,pCHS,sizeof(CHSTRUCT)); GetItemSize(hwnd,pCHS,&si,iCtrlWidth); rcClient.left = rcClient.top = 0; rcClient.right = si.cx; rcClient.bottom = si.cy; } else GetClientRect(hwnd,&rcClient); bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 255; bf.AlphaFormat = AC_SRC_ALPHA; uAlign = pCHS->chf.uAlign; if (lExStyle & WS_EX_RIGHT) { if (uAlign==CH_LEFT) uAlign=CH_RIGHT; else if (uAlign==CH_RIGHT) uAlign=CH_LEFT; } hBufferBitmap = CreateCompatibleBitmap(hDC,rcClient.right,rcClient.bottom); if (!hBufferBitmap) return; hBufferDC = CreateCompatibleDC(hDC); if (!hBufferDC) { DeleteObject(hBufferBitmap); return; } hOldBufferBitmap = SelectObject(hBufferDC,hBufferBitmap); if (bPaintBackground) { hBrush = (HBRUSH)SendMessage(GetParent(hwnd),WM_CTLCOLORSTATIC,(WPARAM)hBufferDC,(LPARAM)hwnd); if (((ULONG)(hBrush))>1) FillRect(hBufferDC,&rcClient,hBrush); } else BitBlt(hBufferDC,0,0,rcClient.right,rcClient.bottom,hDC,ptOffset.x,ptOffset.y,SRCCOPY); hDCMem = CreateCompatibleDC(hDC); switch(pCHS->iState) { case ITEMSTATE_COLD: hOldFont = SelectObject(hBufferDC,pCHS->hFontNormal); iOldColor = SetTextColor(hBufferDC,pCHS->chf.crNormal); break; case ITEMSTATE_PRESSED: hOldFont = SelectObject(hBufferDC,pCHS->hFontHot); iOldColor = SetTextColor(hBufferDC,pCHS->chf.crHot); break; case ITEMSTATE_HOT: hOldFont = SelectObject(hBufferDC,pCHS->hFontHot); iOldColor = SetTextColor(hBufferDC,pCHS->chf.crHot); break; default: hOldFont = SelectObject(hBufferDC,pCHS->hFontNormal); iOldColor = SetTextColor(hBufferDC,GetSysColor(COLOR_GRAYTEXT)); break; } iOldBkMode = SetBkMode(hBufferDC,TRANSPARENT); if (lStyle & CHS_PANEHEADER) { if (lStyle & CHS_SPECIALGROUP) { if (g_sEBI.bPreXP) { FillRect(hBufferDC,&pCHS->rcBackground,GetSysColorBrush(COLOR_HIGHLIGHT)); } else { AlphaBlendHeaderBitmap(hBufferDC,hDCMem,g_sEBI.headerspecial.hAlphaBmpListHeader, &pCHS->rcBackground, g_sEBI.headerspecial.iHeaderBmpWidth, g_sEBI.headerspecial.iHeaderBmpHeight); } } else { if (g_sEBI.bPreXP) { FillRect(hBufferDC,&pCHS->rcBackground,GetSysColorBrush(COLOR_3DFACE)); } else { AlphaBlendHeaderBitmap(hBufferDC,hDCMem,g_sEBI.headernormal.hAlphaBmpListHeader, &pCHS->rcBackground, g_sEBI.headernormal.iHeaderBmpWidth, g_sEBI.headernormal.iHeaderBmpHeight); } } } if (lStyle & CHS_PANEHEADER) { if (lStyle & CHS_SPECIALGROUP) // special pane header { iArrWidth = g_sEBI.headerspecial.iBmpArrowWidth; iArrHeight = g_sEBI.headerspecial.iBmpArrowHeight; phBitmap = pCHS->bExpanded ? g_sEBI.headerspecial.hAlphaBmpArrowUp : g_sEBI.headerspecial.hAlphaBmpArrowDn; } else // normal pane header { iArrWidth = g_sEBI.headernormal.iBmpArrowWidth; iArrHeight = g_sEBI.headernormal.iBmpArrowHeight; phBitmap = pCHS->bExpanded ? g_sEBI.headernormal.hAlphaBmpArrowUp : g_sEBI.headernormal.hAlphaBmpArrowDn; } } else // group header { if (g_sEBI.bPreXP) { iArrWidth = g_sEBI.iBmpPreXPArrowWidth; iArrHeight = g_sEBI.iBmpPreXPArrowHeight; phBitmap = pCHS->bExpanded ? g_sEBI.hAlphaPreXPBmpArrowUp : g_sEBI.hAlphaPreXPBmpArrowDn; } else { iArrWidth = g_sEBI.headernormal.iBmpArrowWidth; iArrHeight = g_sEBI.headernormal.iBmpArrowHeight; phBitmap = pCHS->bExpanded ? g_sEBI.headernormal.hAlphaBmpArrowUp : g_sEBI.headernormal.hAlphaBmpArrowDn; } } dy = 0; switch(pCHS->iState) { case ITEMSTATE_COLD: idx = 0; break; case ITEMSTATE_PRESSED: idx = 2; if (phBitmap[idx]==NULL) { idx = 1; // dy = 1; } break; case ITEMSTATE_HOT: idx = 1; break; default: idx = 0; break; } hOldBitmap = SelectObject(hDCMem,phBitmap[idx]); AlphaBlend(hBufferDC,pCHS->rcButton.left, pCHS->rcButton.top+dy, iArrWidth, iArrHeight, hDCMem, 0, 0, iArrWidth, iArrHeight, bf); SelectObject(hDCMem,hOldBitmap); if ((g_sEBI.bPreXP) && (lStyle & CHS_PANEHEADER)) { if (pCHS->iState==ITEMSTATE_HOT) { hOldPen=SelectObject(hBufferDC,pCHS->hLightPen); MoveToEx(hBufferDC,pCHS->rcButton.left,pCHS->rcButton.bottom+dy-1,NULL); LineTo(hBufferDC,pCHS->rcButton.left,pCHS->rcButton.top+dy); LineTo(hBufferDC,pCHS->rcButton.right,pCHS->rcButton.top+dy); SelectObject(hBufferDC,hOldPen); hOldPen=SelectObject(hBufferDC,pCHS->hShadowPen); MoveToEx(hBufferDC,pCHS->rcButton.right-1,pCHS->rcButton.top+dy,NULL); LineTo(hBufferDC,pCHS->rcButton.right-1,pCHS->rcButton.bottom+dy-1); LineTo(hBufferDC,pCHS->rcButton.left,pCHS->rcButton.bottom+dy-1); SelectObject(hBufferDC,hOldPen); } else if (pCHS->iState==ITEMSTATE_PRESSED) { hOldPen=SelectObject(hBufferDC,pCHS->hShadowPen); MoveToEx(hBufferDC,pCHS->rcButton.left,pCHS->rcButton.bottom+dy-1,NULL); LineTo(hBufferDC,pCHS->rcButton.left,pCHS->rcButton.top+dy); LineTo(hBufferDC,pCHS->rcButton.right,pCHS->rcButton.top+dy); SelectObject(hBufferDC,hOldPen); hOldPen=SelectObject(hBufferDC,pCHS->hLightPen); MoveToEx(hBufferDC,pCHS->rcButton.right-1,pCHS->rcButton.top+dy,NULL); LineTo(hBufferDC,pCHS->rcButton.right-1,pCHS->rcButton.bottom+dy-1); LineTo(hBufferDC,pCHS->rcButton.left,pCHS->rcButton.bottom+dy-1); SelectObject(hBufferDC,hOldPen); } } if ((lStyle & CHS_PANEHEADER) && (pCHS->chf.hIList)) { ImageList_Draw(pCHS->chf.hIList,pCHS->chf.iIIdx,hBufferDC, pCHS->rcIcon.left,pCHS->rcIcon.top,ILD_TRANSPARENT); } szText[0]=0x00; GetWindowText(hwnd,szText,256); memcpy(&rcText,&pCHS->rcText,sizeof(RECT)); if (lStyle & CHS_FOCUSRECT) { if (pCHS->bFocus) DrawFocusRect(hBufferDC,&rcText); rcText.left++; rcText.right--; rcText.top++; rcText.bottom--; } if (lStyle & CHS_WORDBREAK) // multiline, use current control width { if (pCHS->bMultiLine) uDTStyle = DT_EXTERNALLEADING|DT_WORDBREAK; else uDTStyle = DT_SINGLELINE|DT_NOCLIP; } else { if (lStyle & CHS_END_ELLIPSIS) // singleline, use current control width { uDTStyle = DT_END_ELLIPSIS|DT_SINGLELINE; } else // singleline, ignore current control width { uDTStyle = DT_SINGLELINE|DT_NOCLIP; } } switch(pCHS->chf.uAlign) { case CH_CENTER: uDTStyle |= DT_CENTER; break; case CH_RIGHT: uDTStyle |= DT_RIGHT; break; default: uDTStyle |= DT_LEFT; break; } if (lExStyle & WS_EX_RTLREADING) uDTStyle |= DT_RTLREADING; DrawTextEx(hBufferDC,szText,lstrlen(szText),&rcText,uDTStyle,NULL); SetBkMode(hBufferDC,iOldBkMode); SetTextColor(hBufferDC,iOldColor); SelectObject(hBufferDC,hOldFont); if (hDCMem) DeleteDC(hDCMem); BitBlt(hDC,ptOffset.x,ptOffset.y,rcClient.right,rcClient.bottom,hBufferDC,0,0,SRCCOPY); SelectObject(hBufferDC,hOldBufferBitmap); DeleteDC(hBufferDC); DeleteObject(hBufferBitmap); if (iCtrlWidth!=-1) memcpy(pCHS,&CHSSave,sizeof(CHSTRUCT)); }