/*--------------------------------------------------------------------------* * * Microsoft Windows * Copyright (C) Microsoft Corporation, 1992 - 1999 * * File: caption.cpp * * Contents: Implementation file for caption helper functions * * History: 19-Aug-98 jeffro Created * *--------------------------------------------------------------------------*/ #include "stdafx.h" #include "caption.h" #include "fontlink.h" #include "util.h" static void ComputeCaptionRects (CFrameWnd* pwnd, CRect& rectFullCaption, CRect& rectCaptionText, NONCLIENTMETRICS* pncm); static bool GradientFillRect (HDC hdc, LPCRECT pRect, bool fActive); static bool GradientFillRect (HDC hdc, LPCRECT pRect, COLORREF clrGradientLeft, COLORREF clrGradientRight); /*+-------------------------------------------------------------------------* * DrawFrameCaption * * *--------------------------------------------------------------------------*/ bool DrawFrameCaption (CFrameWnd* pwndFrame, bool fActive) { /* * whistler always does the right thing, so short out if we're running there */ if (IsWhistler()) return (false); CWindowDC dc(pwndFrame); NONCLIENTMETRICS ncm; ncm.cbSize = sizeof (ncm); SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); /* * create the caption font and select it into the DC */ CFont font; font.CreateFontIndirect (&ncm.lfCaptionFont); CFont* pOldFont = dc.SelectObject (&font); /* * get the text to draw */ CString strCaption; pwndFrame->GetWindowText (strCaption); /* * create CFontLinker and CRichText objects to determine if we * need to draw the text ourselves */ USES_CONVERSION; CRichText rt (dc, T2CW (strCaption)); CFontLinker fl; if (!fl.ComposeRichText(rt) || rt.IsDefaultFontSufficient()) { dc.SelectObject (pOldFont); return (false); } /*-------------------------------------------------------*/ /* if we get here, the default drawing isn't sufficient; */ /* draw the caption ourselves */ /*-------------------------------------------------------*/ /* * get the bounding rects for the full caption and the text portion */ CRect rectFullCaption; CRect rectCaptionText; ComputeCaptionRects (pwndFrame, rectFullCaption, rectCaptionText, &ncm); /* * clip output to the caption text rect, to minimize destruction * in the event that something dire happens */ dc.IntersectClipRect (rectCaptionText); /* * gradient-fill the full caption rect (not just the title rect) * so the gradient will overlay seamlessly */ if (!GradientFillRect (dc, rectFullCaption, fActive)) { const int nBackColorIndex = (fActive) ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION; dc.FillSolidRect (rectCaptionText, GetSysColor (nBackColorIndex)); } /* * set up text colors and background mix mode */ const int nTextColorIndex = (fActive) ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT; COLORREF clrText = dc.SetTextColor (GetSysColor (nTextColorIndex)); int nBkMode = dc.SetBkMode (TRANSPARENT); /* * draw the text */ rt.Draw (rectCaptionText, fl.GetDrawTextFlags ()); /* * restore the DC */ dc.SetTextColor (clrText); dc.SetBkMode (nBkMode); dc.SelectObject (pOldFont); return (true); } /*+-------------------------------------------------------------------------* * ComputeCaptionRects * * *--------------------------------------------------------------------------*/ static void ComputeCaptionRects ( CFrameWnd* pwnd, CRect& rectFullCaption, CRect& rectCaptionText, NONCLIENTMETRICS* pncm) { /* * start with the full window rect, normalized around (0,0) */ pwnd->GetWindowRect (rectFullCaption); rectFullCaption.OffsetRect (-rectFullCaption.left, -rectFullCaption.top); /* * assume sizing border */ rectFullCaption.InflateRect (-GetSystemMetrics (SM_CXSIZEFRAME), -GetSystemMetrics (SM_CYSIZEFRAME)); /* * correct the height */ rectFullCaption.bottom = rectFullCaption.top + pncm->iCaptionHeight; /* * assume a system menu */ rectCaptionText = rectFullCaption; rectCaptionText.left += pncm->iCaptionWidth + 2; /* * assume min, max, close buttons */ rectCaptionText.right -= pncm->iCaptionWidth * 3; } /*+-------------------------------------------------------------------------* * GradientFillRect * * *--------------------------------------------------------------------------*/ static bool GradientFillRect (HDC hdc, LPCRECT pRect, bool fActive) { #if (WINVER < 0x0500) #define COLOR_GRADIENTACTIVECAPTION 27 #define COLOR_GRADIENTINACTIVECAPTION 28 #endif int nLeftColor = (fActive) ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION; int nRightColor = (fActive) ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION; return (GradientFillRect (hdc, pRect, GetSysColor (nLeftColor), GetSysColor (nRightColor))); } /*+-------------------------------------------------------------------------* * GradientFillRect * * *--------------------------------------------------------------------------*/ static bool GradientFillRect (HDC hdc, LPCRECT pRect, COLORREF clrGradientLeft, COLORREF clrGradientRight) { #if (WINVER < 0x0500) #define SPI_GETGRADIENTCAPTIONS 0x1008 #endif typedef BOOL (WINAPI* GradientFillFuncPtr)( HDC hdc, CONST PTRIVERTEX pVertex, DWORD dwNumVertex, CONST PVOID pMesh, DWORD dwNumMesh, DWORD dwMode); // Query if gradient caption enabled, if query fails assume disabled BOOL bGradientEnabled; if (!SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradientEnabled, 0)) bGradientEnabled = FALSE; if (!bGradientEnabled) return (false); static GradientFillFuncPtr pfnGradientFill = NULL; static bool fAttemptedGetProcAddress = false; // Locate GradientFill function if (!fAttemptedGetProcAddress) { fAttemptedGetProcAddress = true; HINSTANCE hInst = LoadLibrary(TEXT("msimg32.dll")); if (hInst) pfnGradientFill = (GradientFillFuncPtr)GetProcAddress(hInst, "GradientFill"); } if (pfnGradientFill == NULL) return (false); // Do gradient fill TRIVERTEX vert[2] ; vert [0].x = pRect->left; vert [0].y = pRect->top; vert [0].Red = (clrGradientLeft << 8) & 0xff00; vert [0].Green = (clrGradientLeft) & 0xff00; vert [0].Blue = (clrGradientLeft >> 8) & 0xff00; vert [0].Alpha = 0x0000; vert [1].x = pRect->right; vert [1].y = pRect->bottom; vert [1].Red = (clrGradientRight << 8) & 0xff00; vert [1].Green = (clrGradientRight) & 0xff00; vert [1].Blue = (clrGradientRight >> 8) & 0xff00; vert [1].Alpha = 0x0000; GRADIENT_RECT gRect[1]; gRect[0].UpperLeft = 0; gRect[0].LowerRight = 1; (*pfnGradientFill) (hdc, vert, countof (vert), gRect, countof (gRect), GRADIENT_FILL_RECT_H); return (true); }