WindowsXP-SP1/admin/activec/conui/caption.cpp
2020-09-30 16:53:49 +02:00

253 lines
7.6 KiB
C++

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