{******************************************************************************} { CnPack For Delphi/C++Builder } { 中国人自己的开放源码第三方开发包 } { (C)Copyright 2001-2018 CnPack 开发组 } { ------------------------------------ } { } { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 } { 改和重新发布这一程序。 } { } { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 } { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 } { } { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 } { 还没有,可访问我们的网站: } { } { 网站地址:http://www.cnpack.org } { 电子邮件:master@cnpack.org } { } {******************************************************************************} unit CnSkinStdCtrls; interface uses Windows, Messages, SysUtils, Classes, Controls, StdCtrls, Graphics, IniFiles, Forms, ExtCtrls, CnSkinTheme; type TUnderline = (ulNone, ulHot, ulAlways); TCnSkinGroupBox = class(TGroupBox) private procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected { Protected declarations } public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } end; TCnSkinLabel = class(TLabel) private FHotColor: TColor; FHot: Boolean; FUnderline: TUnderline; procedure SetUnderline(Value: TUnderline); procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; protected procedure Paint; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property HotColor: TColor read FHotColor write FHotColor; property Underline: TUnderline read FUnderline write SetUnderline; end; TCnSkinEdit = class(TEdit) private procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; protected { Protected declarations } public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } end; TCnSkinMemo = class(TMemo) private FDownButton: TScrollBarButton; FOverButton: TScrollBarButton; procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; procedure WMNCHittest(var Message: TWMNCHittest); message WM_NCHITTEST; procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; procedure WMNCLButtonUp(var Message: TWMNCLButtonUp); message WM_NCLBUTTONUP; procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; protected procedure CreateParams(var Params: TCreateParams); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; TButtonState = (bsDefault, bsOver, bsDown, bsDisabled); TCnSkinComboBox = class(TComboBox) private FButtonState: TButtonState; procedure SetButtonState(Value: TButtonState); procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected procedure CreateParams(var Params: TCreateParams); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; TCnSkinButton = class(TButton) private FButtonState: TButtonState; procedure SetButtonState(Value: TButtonState); procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected procedure CreateParams(var Params: TCreateParams); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } end; TCnSkinCheckBox = class(TCheckBox) private FButtonState: TButtonState; procedure SetButtonState(Value: TButtonState); procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected procedure CreateParams(var Params: TCreateParams); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } end; TCnSkinRadioButton = class(TRadioButton) private FButtonState: TButtonState; procedure SetButtonState(Value: TButtonState); procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected procedure CreateParams(var Params: TCreateParams); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } end; TCnSkinListBox = class(TListBox) private FDownButton: TScrollBarButton; FOverButton: TScrollBarButton; FScrollBarVisible: Boolean; procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; procedure WMNCHittest(var Message: TWMNCHittest); message WM_NCHITTEST; procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; procedure WMNCLButtonUp(var Message: TWMNCLButtonUp); message WM_NCLBUTTONUP; procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; protected procedure CreateParams(var Params: TCreateParams); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; TCnSkinScrollBar = class(TScrollBar) private FOverButton: TScrollBarButton; FDownButton: TScrollBarButton; procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE; procedure WMNCHittest(var Message: TWMNCHittest); message WM_NCHITTEST; procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN; procedure WMNCLButtonUp(var Message: TWMNCLButtonUp); message WM_NCLBUTTONUP; procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; protected procedure CreateParams(var Params: TCreateParams); override; procedure Change; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published end; TCnSkinStaticText = class(TStaticText) private FHotColor: TColor; FHot: Boolean; FUnderline: TUnderline; procedure SetUnderline(Value: TUnderline); procedure CMThemeChange(var Message: TMessage); message CM_THEMECHANGE; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected { Protected declarations } public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property HotColor: TColor read FHotColor write FHotColor; property Underline: TUnderline read FUnderline write SetUnderline; end; //procedure ResetSkin(SkinPath: string; IniFile: TIniFile); implementation uses Consts; procedure DrawGroupBox(Control: TGroupBox); var Canvas: TControlCanvas; R: TRect; begin Canvas := TControlCanvas.Create; Canvas.Control := Control; Canvas.Lock; try Canvas.Brush := Control.Brush; Canvas.Pen.Color := CnSkinThemes.CurrentSkin.ShadowColor; Canvas.Font := Control.Font; Canvas.FillRect(Control.ClientRect); R := Control.ClientRect; R.Top := Canvas.TextHeight(Control.Caption) div 2; Canvas.Rectangle(R); R.Top := 0; R.Left := 8; DrawText(Canvas.Handle, PChar(Control.Caption), -1, R, DT_LEFT or DT_TOP); finally Canvas.Unlock; Canvas.Free; end; end; procedure DrawBorder(Control: TWinControl); var Canvas: TCanvas; RC, RW: TRect; begin Canvas := TCanvas.Create; Canvas.Handle := GetWindowDC(Control.Handle); try Windows.GetClientRect(Control.Handle, RC); GetWindowRect(Control.Handle, RW); MapWindowPoints(0, Control.Handle, RW, 2); OffsetRect(RC, -RW.Left, -RW.Top); ExcludeClipRect(Canvas.Handle, RC.Left, RC.Top, RC.Right, RC.Bottom); RC := Rect(0, 0, Control.Width, Control.Height); Canvas.Pen.Color := CnSkinThemes.CurrentSkin.ShadowColor; Canvas.Brush := Control.Brush; Canvas.Rectangle(RC); finally ReleaseDC(Control.Handle, Canvas.Handle); Canvas.Free; end; end; procedure DrawCombo(Control: TComboBox; State: TButtonState); var Canvas: TControlCanvas; H: Integer; SrcR, DestR: TRect; begin Canvas := TControlCanvas.Create; Canvas.Control := Control; try Canvas.Brush := Control.Brush; Canvas.Pen.Color := CnSkinThemes.CurrentSkin.ShadowColor; Canvas.Rectangle(Control.ClientRect); DestR.Top := 1; DestR.Bottom := Control.Height -1; DestR.Right := Control.Width -1; DestR.Left := DestR.Right - GetSystemMetrics(SM_CXHTHUMB) - 1; H := CnSkinThemes.CurrentSkin.ComboBmp.Height div 6; SrcR := Rect(0, 0, CnSkinThemes.CurrentSkin.ComboBmp.Width, H); OffsetRect(SrcR, 0, Ord(State) * H); Canvas.CopyRect(DestR, CnSkinThemes.CurrentSkin.ComboBmp.Canvas, SrcR); SrcR := Rect(0, 0, CnSkinThemes.CurrentSkin.ComboBmp.Width, H); if State = bsDisabled then OffsetRect(SrcR, 0, 5 * H) else OffsetRect(SrcR, 0, 4 * H); Inc(DestR.Left, (DestR.Right - DestR.Left - CnSkinThemes.CurrentSkin.ComboBmp.Width) div 2); DestR.Right := DestR.Left + CnSkinThemes.CurrentSkin.ComboBmp.Width; Canvas.Brush.Style := bsClear; Canvas.BrushCopy(DestR, CnSkinThemes.CurrentSkin.ComboBmp, SrcR, clFuchsia); finally Canvas.Free; end; end; procedure DrawButton(Control: TButton; State: TButtonState); var Canvas: TControlCanvas; SrcY, W, H: Integer; SrcR, DestR: TRect; begin Canvas := TControlCanvas.Create; Canvas.Control := Control; Canvas.Lock; try W := CnSkinThemes.CurrentSkin.ButtonBmp.Width div 3; H := CnSkinThemes.CurrentSkin.ButtonBmp.Height div 5; if (GetFocus = Control.Handle) and (State = bsDefault) then SrcY := CnSkinThemes.CurrentSkin.ButtonBmp.Height - H else SrcY := Ord(State) * H; SrcR := Rect(0, SrcY, W, SrcY + H); DestR := Rect(0, 0, W, Control.Height); Canvas.CopyRect(DestR, CnSkinThemes.CurrentSkin.ButtonBmp.Canvas, SrcR); OffsetRect(SrcR, W, 0); DestR.Left := W; DestR.Right := Control.Width - W; Canvas.CopyRect(DestR, CnSkinThemes.CurrentSkin.ButtonBmp.Canvas, SrcR); SrcR.Right := CnSkinThemes.CurrentSkin.ButtonBmp.Width; SrcR.Left := SrcR.Right - W; DestR.Left := DestR.Right; DestR.Right := Control.Width; Canvas.CopyRect(DestR, CnSkinThemes.CurrentSkin.ButtonBmp.Canvas, SrcR); Canvas.Brush.Style := bsClear; Canvas.Font := Control.Font; if not Control.Enabled then Canvas.Font.Color := clGray; DestR.Left := 0; DrawText(Canvas.Handle, PChar(Control.Caption), -1, DestR, DT_CENTER or DT_VCENTER or DT_SINGLELINE); finally Canvas.Unlock; Canvas.Free; end; end; procedure DrawCheckBox(Control: TCheckBox; State: TButtonState); var Canvas: TControlCanvas; SrcR, DestR: TRect; W: Integer; begin Canvas := TControlCanvas.Create; Canvas.Control := Control; Canvas.Lock; try W := CnSkinThemes.CurrentSkin.CheckBmp.Width; SrcR := Rect(0, 0, W, W); DestR := SrcR; OffsetRect(DestR, 0, (Control.Height - W) div 2); OffsetRect(SrcR, 0, (Ord(State) + Ord(Control.State) * 4) * W); Canvas.CopyRect(DestR, CnSkinThemes.CurrentSkin.CheckBmp.Canvas, SrcR); finally Canvas.Unlock; Canvas.Free; end; end; procedure DrawRadio(Control: TRadioButton; State: TButtonState); var Canvas: TControlCanvas; SrcR, DestR: TRect; W: Integer; begin Canvas := TControlCanvas.Create; Canvas.Control := Control; Canvas.Lock; try W := CnSkinThemes.CurrentSkin.RadioBmp.Width; SrcR := Rect(0, 0, W, W); DestR := SrcR; OffsetRect(DestR, 0, (Control.Height - W) div 2); OffsetRect(SrcR, 0, (Ord(State) + Ord(Control.Checked) * 4) * W); Canvas.CopyRect(DestR, CnSkinThemes.CurrentSkin.RadioBmp.Canvas, SrcR); finally Canvas.Unlock; Canvas.Free; end; end; procedure DrawScrollBar2(Canvas: TCanvas; R: TRect; I1, I2: Integer; Down: TScrollBarButton; Kind: TScrollBarKind; Enabled: Boolean); const Colors: array[Boolean] of TColor = (clGray, clBlack); DownStyles: array[Boolean] of Integer = (BDR_RAISEDINNER, BDR_SUNKENOUTER); var DestR: TRect; DestX, DestY, DestW: Integer; begin Canvas.Brush.Color := CnSkinThemes.CurrentSkin.FaceColor; Canvas.FillRect(R); Canvas.Pen.Color := Colors[Enabled]; Canvas.Brush.Color := Colors[Enabled]; if Kind = sbHorizontal then begin DestW := R.Bottom - R.Top; DestR := R; DestR.Right := DestR.Left + DestW; DrawEdge(Canvas.Handle, DestR, DownStyles[Down = sbLeft], BF_RECT); DestX := (DestW - 4) div 2 + R.Left; DestY := (DestW - 6) div 2 + R.Top; Canvas.Polygon([Point(DestX, DestY + 3), Point(DestX + 3, DestY + 6), Point(DestX + 3, DestY), Point(DestX, DestY + 3)]); OffsetRect(DestR, R.Right - R.Left - DestW, 0); DestX := R.Right + R.Left - DestX -1; Canvas.Polygon([Point(DestX, DestY + 3), Point(DestX - 3, DestY + 6), Point(DestX - 3, DestY), Point(DestX, DestY + 3)]); DrawEdge(Canvas.Handle, DestR, DownStyles[Down = sbRight], BF_RECT); DestR.Left := I1; DestR.Right := DestR.Left + I2; if Enabled then DrawEdge(Canvas.Handle, DestR, DownStyles[Down = sbButton], BF_RECT); end else begin DestW := R.Right - R.Left; DestR := R; DestR.Bottom := DestR.Top + DestW; DrawEdge(Canvas.Handle, DestR, DownStyles[Down = sbUp], BF_RECT); DestX := (DestW - 6) div 2 + R.Left; DestY := (DestW - 4) div 2 + R.Top; Canvas.Polygon([Point(DestX, DestY + 3), Point(DestX + 6, DestY + 3), Point(DestX + 3, DestY), Point(DestX, DestY + 3)]); OffsetRect(DestR, 0, R.Bottom - R.Top - DestW); DestY := R.Bottom - R.Top - DestY -1; Canvas.Polygon([Point(DestX, DestY - 3), Point(DestX + 6, DestY - 3), Point(DestX + 3, DestY), Point(DestX, DestY - 3)]); DrawEdge(Canvas.Handle, DestR, DownStyles[Down = sbDown], BF_RECT); DestR.Top := I1; DestR.Bottom := DestR.Top + I2; if Enabled then DrawEdge(Canvas.Handle, DestR, DownStyles[Down = sbButton], BF_RECT); end; end; procedure DrawMemo(Control: TMemo; Over, Down: TScrollBarButton); var Canvas: TCanvas; R, R2: TRect; I, I1, I2: Integer; Enabled: Boolean; procedure DrawMemoScrollBar(Kind: TScrollBarKind); begin R2 := R; if Kind = sbHorizontal then begin Inc(R2.Left); R2.Top := R2.Bottom - SBSIZE; if Control.ScrollBars = ssBoth then Dec(R2.Right, SBSIZE); I1 := R2.Left + SBSIZE; I := R2.Right - R2.Left; case Over of sbButton: Over := sbNone; sbButtonH: Over := sbButton; end; case Down of sbButton: Down := sbNone; sbButtonH: Down := sbButton; end; end else begin Inc(R2.Top); R2.Left := R2.Right - SBSIZE; if Control.ScrollBars = ssBoth then Dec(R2.Bottom, SBSIZE); I1 := R2.Top + SBSIZE; I := R2.Bottom - R2.Top; end; Enabled := Control.Enabled; if Enabled then Enabled := CnGetScrollInfo(Control, I, I1, I2, Kind); CnDrawScrollBar(Canvas, R2, I1, I2, Over, Down, Kind, Enabled); end; begin Canvas := TCanvas.Create; Canvas.Handle := GetWindowDC(Control.Handle); try R := Rect(0, 0, Control.Width, Control.Height); Canvas.Pen.Color := CnSkinThemes.CurrentSkin.ShadowColor; Canvas.Brush.Style := bsClear; Canvas.Rectangle(R); Dec(R.Right); Dec(R.Bottom); Canvas.Font := Control.Font; case Control.ScrollBars of ssBoth: begin R2 := R; R2.Left := R2.Right - SBSIZE; R2.Top := R2.Bottom - SBSIZE; Canvas.Brush.Color := CnSkinThemes.CurrentSkin.FaceColor; Canvas.FillRect(R2); DrawMemoScrollBar(sbVertical); DrawMemoScrollBar(sbHorizontal); end; ssVertical: DrawMemoScrollBar(sbHorizontal); ssHorizontal: DrawMemoScrollBar(sbVertical); end; finally ReleaseDC(Control.Handle, Canvas.Handle); Canvas.Free; end; end; procedure ScrollMemo(Control: TMemo; Count: Integer; Kind: TScrollBarKind); begin if Kind = sbVertical then SendMessage(Control.Handle, EM_LINESCROLL, 0, Count) else SendMessage(Control.Handle, EM_LINESCROLL, Count, 0); end; procedure DrawListBox(Control: TListBox; Over, Down: TScrollBarButton); var Canvas: TCanvas; R: TRect; H, I1, I2: Integer; begin Canvas := TCanvas.Create; Canvas.Handle := GetWindowDC(Control.Handle); try R := Rect(0, 0, Control.Width, Control.Height); Canvas.Pen.Color := CnSkinThemes.CurrentSkin.ShadowColor; Canvas.Brush.Style := bsClear; Canvas.Rectangle(R); H := Control.Height - 2; I1 := SBSIZE + 1; if CnGetScrollInfo(Control, H, I1, I2, sbVertical) then begin Dec(R.Right); Dec(R.Bottom); Inc(R.Top); R.Left := R.Right - SBSIZE; CnDrawScrollBar(Canvas, R, I1, I2, Over, Down, sbVertical, Control.Enabled); end; finally ReleaseDC(Control.Handle, Canvas.Handle); Canvas.Free; end; end; procedure DrawScrollBar(Control: TScrollBar; Over, Down: TScrollBarButton); var I, I1, I2: Integer; Canvas: TCanvas; R: TRect; begin with Control do begin if Kind = sbHorizontal then begin I := Width - Height - Height; I2 := Height; end else begin I := Height - Width - Width; I2 := Width; end; if PageSize > 0 then begin I2 := I * PageSize div Max; if I2 < 10 then I2 := 10; end; if Kind = sbHorizontal then I1 := (I - I2) * Position div Max + Height else I1 := (I - I2) * Position div Max + Width; R := Rect(0, 0, Width, Height); Canvas := TCanvas.Create; Canvas.Handle := GetWindowDC(Handle); try CnDrawScrollBar(Canvas, R, I1, I2, Over, Down, Kind, Enabled); finally ReleaseDC(Handle, Canvas.Handle); Canvas.Free; end; end; end; {TCnSkinGroupBox} constructor TCnSkinGroupBox.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); end; destructor TCnSkinGroupBox.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinGroupBox.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinGroupBox.WMPaint(var Message: TWMPaint); begin inherited; if CnSkinThemes.Active then DrawGroupBox(Self); end; {TCnSkinLabel} constructor TCnSkinLabel.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); FHotColor := clBlue; end; destructor TCnSkinLabel.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinLabel.SetUnderline(Value: TUnderline); begin if Value <> FUnderline then begin FUnderline := Value; Repaint; end; end; procedure TCnSkinLabel.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinLabel.CMFontChanged(var Message: TMessage); begin if not FHot then inherited; end; procedure TCnSkinLabel.CMMouseEnter(var Message: TMessage); begin inherited; if not (csDesigning in ComponentState) then begin FHot := True; Repaint; end; end; procedure TCnSkinLabel.CMMouseLeave(var Message: TMessage); begin inherited; if not (csDesigning in ComponentState) then begin FHot := False; Repaint; end; end; procedure TCnSkinLabel.Paint; var SaveColor: TColor; X, W: Integer; begin if FHot then begin SaveColor := Font.Color; Font.Color := FHotColor; end else SaveColor := clBlack; inherited; if (FUnderline = ulAlways) or ((FUnderline = ulHot) and FHot) then begin X := 0; W := Canvas.TextWidth(Caption); case Alignment of taCenter: X := (Width - W) div 2; taRightJustify: X := Width - W; end; Canvas.Pen.Color := Font.Color; Canvas.MoveTo(X, Height -1 ); Canvas.LineTo(X + W, Height - 1); end; if FHot then Font.Color := SaveColor; end; {TCnSkinEdit} constructor TCnSkinEdit.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); end; destructor TCnSkinEdit.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinEdit.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinEdit.WMNCPaint(var Message: TMessage); begin if CnSkinThemes.Active then DrawBorder(Self) else inherited; end; {TCnSkinMemo} constructor TCnSkinMemo.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); FDownButton := sbNone; FOverButton := sbNone; end; destructor TCnSkinMemo.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinMemo.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinMemo.CMThemeChange(var Message: TMessage); begin RecreateWnd; end; procedure TCnSkinMemo.CMMouseLeave(var Message: TMessage); begin if FOverButton <> sbNone then begin FOverButton := sbNone; FDownButton := sbNone; DrawMemo(Self, FOverButton, FDownButton); end; end; procedure TCnSkinMemo.WMNCCalcSize(var Message: TWMNCCalcSize); begin if CnSkinThemes.Active then begin with Message.CalcSize_Params^ do begin Inc(rgrc[0].Left); Inc(rgrc[0].Top); Dec(rgrc[0].Right); if ScrollBars in [ssBoth, ssVertical] then Dec(rgrc[0].Right, SBSIZE); Dec(rgrc[0].Bottom); if ScrollBars in [ssBoth, ssHorizontal] then Dec(rgrc[0].Bottom, SBSIZE); end; end else inherited; end; procedure TCnSkinMemo.WMNCLButtonDown(var Message: TWMNCLButtonDown); var Pt: TPoint; Kind: TScrollBarKind; I, Count, Pos, CharWidth: Integer; begin inherited; if (CnSkinThemes.Active) and (ScrollBars <> ssNone) then begin FDownButton := FOverButton; if FDownButton < sbButton then begin Pos := 0; Kind := sbVertical; I := 0; Pt := ScreenToClient(Point(Message.XCursor, Message.YCursor)); if (Pt.X > Width - SBSIZE - 1) and (ScrollBars <> ssHorizontal) then begin I := Height - 2; if ScrollBars = ssBoth then Dec(I, SBSIZE); Kind := sbVertical; Pos := Pt.Y; end else if (Pt.Y > Height - SBSIZE - 1) and (ScrollBars <> ssVertical) then begin I := Width - 2; if ScrollBars = ssBoth then Dec(I, SBSIZE); Kind := sbHorizontal; Pos := Pt.X; end; Count := CnGetScrollCount(Self, FDownButton, I, Pos, Kind); if Count <> 0 then begin if FDownButton <> sbNone then begin ScrollMemo(Self, Count, Kind); SetTimer(Handle, 1000, 100, nil); end else if Kind = sbHorizontal then begin Pos := GetScrollPos(Handle, Ord(Kind)); if Count > 0 then begin ScrollMemo(Self, 1, Kind); CharWidth := GetScrollPos(Handle, Ord(Kind)) - Pos; Dec(Count, CharWidth); end else begin ScrollMemo(Self, -1, Kind); CharWidth := Pos - GetScrollPos(Handle, Ord(Kind)); Inc(Count, CharWidth); end; ScrollMemo(Self, Count div CharWidth, Kind); end else ScrollMemo(Self, Count, Kind); end else DrawMemo(Self, FOverButton, FDownButton); end else DrawMemo(Self, FOverButton, FDownButton); end; end; procedure TCnSkinMemo.WMNCLButtonUp(var Message: TWMNCLButtonUp); begin inherited; if FDownButton <> sbNone then begin FDownButton := sbNone; DrawMemo(Self, FOverButton, FDownButton); end; end; procedure TCnSkinMemo.WMNCHittest(var Message: TWMNCHittest); var Pt: TPoint; Button: TScrollBarButton; I, I1, I2, Pos, Count, CharWidth: Integer; Kind: TScrollBarKind; begin inherited; if (not CnSkinThemes.Active) or (ScrollBars = ssNone) then Exit; Pt := ScreenToClient(Point(Message.XPos, Message.YPos)); Button := sbNone; if (Pt.X > Width - SBSIZE - 1) and (ScrollBars <> ssHorizontal) then begin Kind := sbVertical; I := Height - 2; if ScrollBars = ssBoth then Dec(I, SBSIZE); if FDownButton = sbButton then begin Count := CnGetScrollCount(Self, FDownButton, I, Pt.Y, Kind); if Count <> 0 then ScrollMemo(Self, Count, Kind); end else if Pt.Y < SBSIZE + 1 then Button := sbUp else if Pt.Y > I - SBSIZE then Button := sbDown else begin I1 := SBSIZE + 1; if CnGetScrollInfo(Self, I, I1, I2, Kind) and (Pt.Y > I1) and (Pt.Y < I1 + I2) then Button := sbButton; end; end else if (Pt.Y > Height - SBSIZE - 1) and (ScrollBars <> ssVertical) then begin Kind := sbHorizontal; I := Width - 2; if ScrollBars = ssBoth then Dec(I, SBSIZE); if FDownButton = sbButtonH then begin Count := CnGetScrollCount(Self, sbButton, I, Pt.X, Kind); if Count <> 0 then begin Pos := GetScrollPos(Handle, 0); if Count > 0 then begin ScrollMemo(Self, 1, Kind); CharWidth := GetScrollPos(Handle, Ord(Kind)) - Pos; Dec(Count, CharWidth); end else begin ScrollMemo(Self, -1, Kind); CharWidth := Pos - GetScrollPos(Handle, Ord(Kind)); Inc(Count, CharWidth); end; ScrollMemo(Self, Count div CharWidth, Kind); end; end else if Pt.X < SBSIZE + 1 then Button := sbLeft else if Pt.X > I - SBSIZE then Button := sbRight else begin I1 := SBSIZE + 1; if CnGetScrollInfo(Self, I, I1, I2, Kind) and (Pt.X > I1) and (Pt.X < I1 + I2) then Button := sbButtonH; end; end else Exit; Message.Result := HTBORDER; if Button <> FOverButton then begin FOverButton := Button; DrawMemo(Self, FOverButton, FDownButton); end; end; procedure TCnSkinMemo.WMNCPaint(var Message: TMessage); begin if CnSkinThemes.Active then DrawMemo(Self, FOverButton, FDownButton) else inherited; end; procedure TCnSkinMemo.WMPaint(var Message: TWMPaint); begin inherited; if CnSkinThemes.Active then DrawMemo(Self, FOverButton, FDownButton); end; procedure TCnSkinMemo.WMTimer(var Message: TWMTimer); var Kind: TScrollBarKind; Count: Integer; begin if FDownButton in [sbUp, sbDown] then Kind := sbVertical else Kind := sbHorizontal; Count := CnGetScrollCount(Self, FDownButton, -1, -1, Kind); if (FDownButton <> sbNone) and (Count <> 0) then ScrollMemo(Self, Count, Kind) else KillTimer(Handle, Message.TimerID); end; {TCnSkinCombo} constructor TCnSkinComboBox.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); end; destructor TCnSkinComboBox.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinComboBox.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinComboBox.SetButtonState(Value: TButtonState); begin if (Value = bsOver) and (FButtonState = bsDown) and (GetKeyState(VK_LBUTTON) < 0) then Exit; if (Value <> FButtonState) then begin FButtonState := Value; Repaint; end; end; procedure TCnSkinComboBox.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinComboBox.CMEnabledChanged(var Message: TMessage); begin inherited; Repaint; end; procedure TCnSkinComboBox.CMMouseLeave(var Message: TMessage); begin SetButtonState(bsDefault); end; procedure TCnSkinComboBox.WMPaint(var Message: TWMPaint); begin inherited; if CnSkinThemes.Active then if Enabled then DrawCombo(Self, FButtonState) else DrawCombo(Self, bsDisabled); end; procedure TCnSkinComboBox.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (Button = mbLeft) and (FButtonState <> bsDefault) then SetButtonState(bsDown); inherited MouseDown(Button, Shift, X, Y); end; procedure TCnSkinComboBox.MouseMove(Shift: TShiftState; X, Y: Integer); begin if (X > Width - GetSystemMetrics(SM_CXHTHUMB) -4) and (X < Width -2) then SetButtonState(bsOver) else SetButtonState(bsDefault); inherited MouseMove(Shift, X, Y); end; procedure TCnSkinComboBox.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (Button = mbLeft) and (FButtonState <> bsDefault) then SetButtonState(bsOver); inherited MouseUp(Button, Shift, X, Y); end; {TCnSkinButton} constructor TCnSkinButton.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); end; destructor TCnSkinButton.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinButton.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinButton.SetButtonState(Value: TButtonState); begin if (Value = bsOver) and (FButtonState = bsDown) and (GetKeyState(VK_LBUTTON) < 0) then Exit; if (Value <> FButtonState) then begin FButtonState := Value; Repaint; end; end; procedure TCnSkinButton.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinButton.CMMouseEnter(var Message: TMessage); begin SetButtonState(bsOver); end; procedure TCnSkinButton.CMMouseLeave(var Message: TMessage); begin SetButtonState(bsDefault); end; procedure TCnSkinButton.WMPaint(var Message: TWMPaint); begin inherited; if CnSkinThemes.Active then if Enabled then DrawButton(Self, FButtonState) else DrawButton(Self, bsDisabled); end; procedure TCnSkinButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then SetButtonState(bsDown); inherited MouseDown(Button, Shift, X, Y); end; procedure TCnSkinButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (Button = mbLeft) and (FButtonState <> bsDefault) then SetButtonState(bsOver); inherited MouseUp(Button, Shift, X, Y); end; {TCnSkinCheck} constructor TCnSkinCheckBox.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); end; destructor TCnSkinCheckBox.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinCheckBox.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinCheckBox.SetButtonState(Value: TButtonState); begin if (Value = bsOver) and (FButtonState = bsDown) and (GetKeyState(VK_LBUTTON) < 0) then Exit; if (Value <> FButtonState) then begin FButtonState := Value; Repaint; end; end; procedure TCnSkinCheckBox.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinCheckBox.CMEnabledChanged(var Message: TMessage); begin inherited; Repaint; end; procedure TCnSkinCheckBox.CMMouseEnter(var Message: TMessage); begin SetButtonState(bsOver); end; procedure TCnSkinCheckBox.CMMouseLeave(var Message: TMessage); begin SetButtonState(bsDefault); end; procedure TCnSkinCheckBox.WMPaint(var Message: TWMPaint); begin inherited; if CnSkinThemes.Active then if Enabled then DrawCheckBox(Self, FButtonState) else DrawCheckBox(Self, bsDisabled); end; procedure TCnSkinCheckBox.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then SetButtonState(bsDown); inherited MouseDown(Button, Shift, X, Y); end; procedure TCnSkinCheckBox.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (Button = mbLeft) and (FButtonState <> bsDefault) then SetButtonState(bsOver); inherited MouseUp(Button, Shift, X, Y); end; {TCnSkinRadio} constructor TCnSkinRadioButton.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); end; destructor TCnSkinRadioButton.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinRadioButton.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinRadioButton.SetButtonState(Value: TButtonState); begin if (Value = bsOver) and (FButtonState = bsDown) and (GetKeyState(VK_LBUTTON) < 0) then Exit; if (Value <> FButtonState) then begin FButtonState := Value; Repaint; end; end; procedure TCnSkinRadioButton.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinRadioButton.CMEnabledChanged(var Message: TMessage); begin inherited; Repaint; end; procedure TCnSkinRadioButton.CMMouseEnter(var Message: TMessage); begin SetButtonState(bsOver); end; procedure TCnSkinRadioButton.CMMouseLeave(var Message: TMessage); begin SetButtonState(bsDefault); end; procedure TCnSkinRadioButton.WMPaint(var Message: TWMPaint); begin inherited; if CnSkinThemes.Active then if Enabled then DrawRadio(Self, FButtonState) else DrawRadio(Self, bsDisabled); end; procedure TCnSkinRadioButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then SetButtonState(bsDown); inherited MouseDown(Button, Shift, X, Y); end; procedure TCnSkinRadioButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var I: Integer; begin if (Button = mbLeft) and (FButtonState <> bsDefault) then begin SetButtonState(bsOver); for I := 0 to Parent.ControlCount - 1 do if Parent.Controls[I] is TCnSkinRadioButton then Parent.Controls[I].Repaint; end; inherited MouseUp(Button, Shift, X, Y); end; {TCnSkinListBox} constructor TCnSkinListBox.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); FOverButton := sbNone; FDownButton := sbNone; FScrollBarVisible := False; end; destructor TCnSkinListBox.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinListBox.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinListBox.CMThemeChange(var Message: TMessage); begin RecreateWnd; end; procedure TCnSkinListBox.CMMouseLeave(var Message: TMessage); begin if FOverButton <> sbNone then begin FOverButton := sbNone; FDownButton := sbNone; DrawListBox(Self, FOverButton, FDownButton); end; end; procedure TCnSkinListBox.WMNCCalcSize(var Message: TWMNCCalcSize); begin if CnSkinThemes.Active then begin with Message.CalcSize_Params^ do begin Inc(rgrc[0].Left); Inc(rgrc[0].Top); Dec(rgrc[0].Right); if FScrollBarVisible then Dec(rgrc[0].Right, SBSIZE); Dec(rgrc[0].Bottom) end; end else inherited; end; procedure TCnSkinListBox.WMNCLButtonDown(var Message: TWMNCLButtonDown); var Pt: TPoint; Count: Integer; begin inherited; if FScrollBarVisible then begin FDownButton := FOverButton; if FDownButton <> sbButton then begin Pt := ScreenToClient(Point(Message.XCursor, Message.YCursor)); Count := CnGetScrollCount(Self, FDownButton, Height - 2, Pt.Y, sbVertical); if Count <> 0 then begin TopIndex := TopIndex + Count; SetTimer(Handle, 1000, 100, nil); end else DrawListBox(Self, FOverButton, FDownButton); end else DrawListBox(Self, FOverButton, FDownButton); end; end; procedure TCnSkinListBox.WMNCLButtonUp(var Message: TWMNCLButtonUp); begin inherited; if FScrollBarVisible and (FDownButton <> sbNone) then begin FDownButton := sbNone; DrawListBox(Self, FOverButton, FDownButton); end; end; procedure TCnSkinListBox.WMNCHittest(var Message: TWMNCHittest); var Pt: TPoint; Button: TScrollBarButton; Count, I1, I2: Integer; begin inherited; if not FScrollBarVisible then Exit; Pt := ScreenToClient(Point(Message.XPos, Message.YPos)); if Pt.X > Width - SBSIZE - 1 then begin Message.Result := HTBORDER; if FDownButton = sbButton then begin Count := CnGetScrollCount(Self, FDownButton, Height - 2, Pt.Y, sbVertical); if Count <> 0 then TopIndex := TopIndex + Count; end else begin Button := sbNone; if Pt.Y < SBSIZE + 1 then Button := sbUp else if Pt.Y > Height - SBSIZE - 1 then Button := sbDown else begin I1 := SBSIZE + 1; if CnGetScrollInfo(Self, Height - 2, I1, I2, sbVertical) and (Pt.Y > I1) and (Pt.Y < I1 + I2) then Button := sbButton; end; if Button <> FOverButton then begin FOverButton := Button; DrawListBox(Self, FOverButton, FDownButton); end; end; end; end; procedure TCnSkinListBox.WMNCPaint(var Message: TMessage); begin if CnSkinThemes.Active then DrawListBox(Self, FoverButton, FDownButton) else inherited; end; procedure TCnSkinListBox.WMPaint(var Message: TWMPaint); var SV: Boolean; begin inherited; if CnSkinThemes.Active then begin SV := Items.Count > ClientHeight div ItemHeight; if SV <> FScrollBarVisible then begin FScrollBarVisible := SV; RecreateWnd; end; if SV then DrawListBox(Self, FDownButton, FOverButton); end; end; procedure TCnSkinListBox.WMTimer(var Message: TWMTimer); var Count: Integer; begin Count := CnGetScrollCount(Self, FDownButton, -1, -1, sbVertical); if (FDownButton <> sbNone) and (Count <> 0) then TopIndex := TopIndex + Count else KillTimer(Handle, Message.TimerID); end; {TCnSkinScrollBar} constructor TCnSkinScrollBar.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); FOverButton := sbNone; FDownButton := sbNone; end; destructor TCnSkinScrollBar.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinScrollBar.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); end; procedure TCnSkinScrollBar.Change; begin inherited; DrawScrollBar(Self, FOverButton, FDownButton); end; procedure TCnSkinScrollBar.CMThemeChange(var Message: TMessage); begin RecreateWnd; end; procedure TCnSkinScrollBar.CMEnabledChanged(var Message: TMessage); begin inherited; DrawScrollBar(Self, FOverButton, FDownButton); end; procedure TCnSkinScrollBar.CMMouseLeave(var Message: TMessage); begin if FOverButton <> sbNone then begin FOverButton := sbNone; DrawScrollBar(Self, FOverButton, FDownButton); end; end; procedure TCnSkinScrollBar.WMNCCalcSize(var Message: TWMNCCalcSize); begin if CnSkinThemes.Active then begin with Message.CalcSize_Params^ do begin Inc(rgrc[0].Top, Height); Inc(rgrc[0].Left, Width); end; end else inherited; end; procedure TCnSkinScrollBar.WMNCLButtonDown(var Message: TWMNCLButtonDown); var Pt: TPoint; begin inherited; if CnSkinThemes.Active then begin FDownButton := FOverButton; case FDownButton of sbUp, sbLeft: if Position > Min then begin Position := Position - 1; SetTimer(Handle, 1000, 100, nil); end else DrawScrollBar(Self, FOverButton, FDownButton); sbDown, sbRight: if Position < Max then begin Position := Position + 1; SetTimer(Handle, 1000, 100, nil); end else DrawScrollBar(Self, FOverButton, FDownButton); sbNone: begin Pt := Parent.ScreenToClient(Point(Message.XCursor, Message.YCursor)); if Kind = sbHorizontal then Position := (Pt.X - Left - Height) * Max div (Width - Height - Height) else Position := (Pt.Y - Top - Width) * Max div (Height - Width - Width); end; else DrawScrollBar(Self, FOverButton, FDownButton); end; end; end; procedure TCnSkinScrollBar.WMNCLButtonUp(var Message: TWMNCLButtonUp); begin inherited; if FDownButton <> sbNone then begin FDownButton := sbNone; DrawScrollBar(Self, FOverButton, FDownButton); end; end; procedure TCnSkinScrollBar.WMNCHittest(var Message: TWMNCHittest); var Pt: TPoint; Button: TScrollBarButton; I, I1, I2: Integer; begin inherited; if CnSkinThemes.Active then begin Pt := Parent.ScreenToClient(Point(Message.XPos, Message.YPos)); Button := sbNone; if Kind = sbHorizontal then begin Dec(Pt.X, Left); if FDownButton = sbButton then Position := (Pt.X - Height) * Max div (Width - Height - Height) else if Pt.X < Height then Button := sbLeft else if Pt.X > Width - Height then Button := sbRight else begin I := Width - Height - Height; if PageSize > 0 then begin I2 := I * PageSize div Max; if I2 < 10 then I2 := 10; end else I2 := Height; I1 := (I - I2) * Position div Max + Height; if (Pt.X > I1) and (Pt.X < I1 + I2) then Button := sbButton; end; end else begin Dec(Pt.Y, Top); if FDownButton = sbButton then Position := (Pt.Y - Width) * Max div (Height - Width - Width) else if Pt.Y < Width then Button := sbUp else if Pt.Y > Height - Width then Button := sbDown else begin I := Height - Width - Width; if PageSize > 0 then begin I2 := I * PageSize div Max; if I2 < 10 then I2 := 10; end else I2 := Width; I1 := (I - I2) * Position div Max + Width; if (Pt.Y > I1) and (Pt.Y < I1 + I2) then Button := sbButton; end; end; if Button <> FOverButton then begin FOverButton := Button; DrawScrollBar(Self, FOverButton, FDownButton); end; Message.Result := HTBORDER; end; end; procedure TCnSkinScrollBar.WMNCPaint(var Message: TMessage); begin if CnSkinThemes.Active then DrawScrollBar(Self, FOverButton, FDownButton) else inherited; end; procedure TCnSkinScrollBar.WMTimer(var Message: TWMTimer); begin case FDownButton of sbUp, sbLeft: if Position > Min then Position := Position - 1 else KillTimer(Handle, Message.TimerID); sbDown, sbRight: if Position < Max then Position := Position + 1 else KillTimer(Handle, Message.TimerID); else KillTimer(Handle, Message.TimerID); end; end; {TCnSkinStatic} constructor TCnSkinStaticText.Create(AOwner: TComponent); begin inherited Create(AOwner); CnSkinThemes.Controls.Add(Self); FHotColor := clBlue; end; destructor TCnSkinStaticText.Destroy; begin CnSkinThemes.Controls.Remove(Self); inherited Destroy; end; procedure TCnSkinStaticText.SetUnderline(Value: TUnderline); begin if Value <> FUnderline then begin FUnderline := Value; Repaint; end; end; procedure TCnSkinStaticText.CMThemeChange(var Message: TMessage); begin Repaint; end; procedure TCnSkinStaticText.CMMouseEnter(var Message: TMessage); begin inherited; if not (csDesigning in ComponentState) then begin FHot := True; Repaint; end; end; procedure TCnSkinStaticText.CMMouseLeave(var Message: TMessage); begin inherited; if not (csDesigning in ComponentState) then begin FHot := False; Repaint; end; end; procedure TCnSkinStaticText.WMPaint(var Message: TWMPaint); const Flags: array[TAlignment] of Longint = (DT_LEFT, DT_RIGHT, DT_CENTER); var X, W: Integer; Canvas: TControlCanvas; R: TRect; begin inherited; Canvas := TControlCanvas.Create; Canvas.Control := Self; try Canvas.Font := Font; Canvas.Brush.Style := bsClear; if FHot then Canvas.Font.Color := FHotColor; R := ClientRect; DrawText(Canvas.Handle, PChar(Caption), -1, R, Flags[Alignment]); if (FUnderline = ulAlways) or ((FUnderline = ulHot) and FHot) then begin X := 0; W := Canvas.TextWidth(Caption); case Alignment of taCenter: X := (Width - W) div 2; taRightJustify: X := Width - W; end; Canvas.Pen.Color := Canvas.Font.Color; Canvas.MoveTo(X, Height - 1); Canvas.LineTo(X + W, Height - 1); end; finally Canvas.Free; end; end; end.