You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
7.6 KiB
252 lines
7.6 KiB
/*--------------------------------------------------------------------------*
|
|
*
|
|
* 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);
|
|
}
|