#include "MAINFORM.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CustomCaption = "Custom Caption";
Caption = "";
WindowCanvas = new TCanvas;
// this code determines if we are running on NT3.X
TOSVersionInfo ver;
ver.dwOSVersionInfoSize = sizeof(TOSVersionInfo);
GetVersionEx( &ver);
if(ver.dwMajorVersion < 4)
{
// if the OS is NT 3.5, the custom caption won't be drawn
// use the Caption property as usual, since the custom
// caption won't be able to draw the string.
IsNT35 = true;
Caption = CustomCaption;
}
else
IsNT35 = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Exit1Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMNCActivate(TWMNCActivate &Msg)
{
Msg.Result = true; // always handle this message;
if ((bool)Msg.Active == false) // if non-active draw default
{ // non-active title bar
DefWindowProc( Handle, Msg.Msg, Msg.Active, 0 );
// add code here to draw caption when window is inactive.
// in this example, we leave the inactive caption alone.
return;
}
TMessage PaintMsg; // if active, do same thing as WMNCPaint
PaintMsg.Msg = Msg.Msg; // create a MSG to pass to WMNCPaint and
PaintMsg.WParam = Msg.Active; // call the function directly so painting
WMNCPaint(PaintMsg); // happens now.
}
void __fastcall TForm1::WMNCPaint(TMessage &Msg)
{
// use default processing to draw min/max/close buttons, menu, and the
// frame. the caption bar is drawn too, but we paint over that later.
DefWindowProc(Handle, Msg.Msg,Msg.WParam,Msg.LParam);
// Check for any reason not to draw the custom caption
if(CanDrawMyCustomCaption() == false)
return;
// create a DC for the entire window, then assign
// the handle to the window canvas
HDC WindowDC = GetWindowDC(Handle);
WindowCanvas->Handle = WindowDC;
CalculateCaptionRect(); // calculate size of caption bar
DrawGradient(); // draw the shaded gradient
DrawIcon(); // patch the icon
DrawCaptionString();
DrawHeartBeatLight(); // draw the LED heartbeat
bool TForm1::CanDrawMyCustomCaption(void)
{
// under certain conditions we don't want to shade the custom caption.
// this function bundles all of the reasons into one.
if (WindowCanvas == 0) // WMNCPaint can execute after
return false; // destructor has been called.
if(Application->Active == false) //can get WM_NCPAINT messages
return false; // when inactive
if(Width < 150) // shading looks poor at very small
return false; // widths
if(IsNT35 == true) // NT has 3.5 has win3 style system menu
return false; // and centered caption text, so forget it
// shading looks poor if its from black to a very light color, Word actually
// shades from white instead of black for light caption colors, we will just not
// shade for light colored captions. Light colors have high RGB values
FinalCaptionColor = TColor(GetSysColor(COLOR_ACTIVECAPTION));
FinalBlueIntensity = GetBValue(FinalCaptionColor);
FinalGreenIntensity= GetGValue(FinalCaptionColor);
FinalRedIntensity = GetRValue(FinalCaptionColor);
// is at least one of the RGB values dark, if not, don't draw the shading
if ((FinalBlueIntensity < 128) || (FinalGreenIntensity < 128) || (FinalRedIntensity < 128) )
return true;
else
return false;
}
void TForm1::CalculateCaptionRect(void)
{
// determine the coordinates of the custom area of the caption. The left, top,
// and bottom must be calculated precisely. The right value is an arbitrary
// value that keeps us away from the min/max buttons.
CaptionRect.Left = GetSystemMetrics(SM_CXFRAME);
CaptionRect.Right= Width- 4*GetSystemMetrics(SM_CXSIZE); // stay away from btns
CaptionRect.Top = GetSystemMetrics(SM_CYFRAME);
CaptionRect.Bottom=CaptionRect.Top + GetSystemMetrics(SM_CYCAPTION)-1;
}
void TForm1::DrawGradient(void)
{
// Shading involves gradually increasing RGB color values from 0 (black)
// to the final RGB value of the caption color. The Increment values
// will be multiplied by 0,1..31 to create 32 shades. The FinalXXX
// values are calculated inside of CanDrawMyCustomGraphics
int BlueIncrement = (FinalBlueIntensity+1) / 32; // max intensity is 255,
int GreenIncrement= (FinalGreenIntensity+1)/32; // adding 1 makes number
int RedIncrement = (FinalRedIntensity+1)/32; // evenly divisible by 32.
TRect Section = CaptionRect;
// SectionWidth represents the width of each gradient section. Caption
// bar will contain 36 gradient sections, 5 sections will be black, the
// remaining 31 sections will be between black and the caption color
int SectionWidth = (CaptionRect.Right - CaptionRect.Left)/36;
TColor FillColor(clBlack);
Section.Right = Section.Left + 5*SectionWidth; //draw 5 sections of black
WindowCanvas->Brush->Color = FillColor; //configure the brush
WindowCanvas->Brush->Style = bsSolid;
WindowCanvas->FillRect(Section); //fill in black sections
Section.Left+=5*SectionWidth; //move section over
for (int j=1;j<=31;j++) // loop through the shades of color
{ // from black to the caption color
Section.Right = Section.Left + SectionWidth; // size the section
FillColor = (TColor) RGB((RedIncrement*j), // create dithered color
(GreenIncrement*j), // based on loop index.
(BlueIncrement*j));
WindowCanvas->Brush->Color = FillColor; // set brush to new color
WindowCanvas->FillRect(Section); // brush fill the section
Section.Left += SectionWidth; // move section over
}
}
void TForm1::DrawIcon(void)
{
// Need to redraw the system icon because DrawGradient just painted
// over it with black. DrawGradient painted over it because the icon
// had the caption color surrounding it.
int IconWidth = GetSystemMetrics(SM_CXSMICON); // calculate width and
int IconHeight= GetSystemMetrics(SM_CYSMICON); // height of icon
TRect Section;
Section.Left=CaptionRect.Left+2; // determine where the icon belongs
Section.Top =CaptionRect.Top +1;
Section.Right=Section.Left + IconWidth; // size the rect to hold the icon
Section.Bottom=Section.Top + IconHeight;
// paint the application icon, could avoid stretching by
// supplying a 16 by 16 icon.
DrawIconEx(WindowCanvas->Handle, Section.Left, Section.Top, // api call
Application->Icon->Handle,IconWidth,IconHeight,0,NULL,DI_NORMAL);
}
void TForm1::DrawCaptionString(void)
{
// need to draw our own caption string. must avoid using the Caption
// form member to avoid flicker
RECT r; // need an API style rect
r.left=CaptionRect.Left + 2 + 16 + 4; // size the rect
r.right=CaptionRect.Right-20;
r.top = CaptionRect.Top;
r.bottom = CaptionRect.Bottom;
SetBkMode(WindowCanvas->Handle,TRANSPARENT); // transparent mode so text
WindowCanvas->Font->Color=clWhite; // does not wipe out shading
WindowCanvas->Font->Style = WindowCanvas->Font->Style << fsBold;
DrawText(WindowCanvas->Handle,CustomCaption.c_str(),CustomCaption.Length(),
&r,DT_SINGLELINE|DT_VCENTER); // draw with vert centered text
}
void TForm1::DrawHeartBeatLight(void)
{
// draw a little LED style heartbeat indicator. this is just an
// ellipse with varying fill color
TRect Section = CaptionRect;
int cYCaption = GetSystemMetrics(SM_CYCAPTION);
if(HeartBeat == true)
WindowCanvas->Brush->Color = (TColor) RGB(0,255,0); // bright green
else
WindowCanvas->Brush->Color = clBlack;
WindowCanvas->Pen->Color=clBlack;
WindowCanvas->Ellipse(Section.Right-cYCaption/2,
Section.Top +cYCaption/4,
Section.Right,
Section.Bottom-cYCaption/4);
}
__fastcall TForm1::~TForm1(void)
{
delete WindowCanvas;
WindowCanvas = 0; // zero canvas so CanDrawMyCustomCaption can
// block use of an invalid pointer.
}