Componentes.Terceros.jvcl/official/3.32/run/JvSwitch.pas

519 lines
14 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvSwitch.PAS, released on 2002-07-04.
The Initial Developers of the Original Code are: Fedor Koshevnikov, Igor Pavluk and Serge Korolev
Copyright (c) 1997, 1998 Fedor Koshevnikov, Igor Pavluk and Serge Korolev
Copyright (c) 2001,2002 SGB Software
All Rights Reserved.
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvSwitch.pas 10612 2006-05-19 19:04:09Z jfudickar $
unit JvSwitch;
{$I jvcl.inc}
interface
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
SysUtils, Classes,
Windows, Messages, Graphics, Controls, Forms, Menus,
{$IFDEF VisualCLX}
Qt,
{$ENDIF VisualCLX}
JvJCLUtils, JvComponent;
type
TTextPos = (tpNone, tpLeft, tpRight, tpAbove, tpBelow);
TSwitchBitmaps = set of Boolean;
TJvSwitch = class(TJvCustomControl)
private
FActive: Boolean;
FBitmaps: array [Boolean] of TBitmap;
FDisableBitmaps: array [Boolean] of TBitmap;
FOnOn: TNotifyEvent;
FOnOff: TNotifyEvent;
FStateOn: Boolean;
FTextPosition: TTextPos;
FBorderStyle: TBorderStyle;
FToggleKey: TShortCut;
FShowFocus: Boolean;
FUserBitmaps: TSwitchBitmaps;
procedure GlyphChanged(Sender: TObject);
procedure SetStateOn(Value: Boolean);
procedure SetTextPosition(Value: TTextPos);
procedure SetBorderStyle(Value: TBorderStyle);
function GetSwitchGlyph(Index: Integer): TBitmap;
procedure SetSwitchGlyph(Index: Integer; Value: TBitmap);
function StoreBitmap(Index: Integer): Boolean;
procedure SetShowFocus(Value: Boolean);
procedure CreateDisabled(Index: Boolean);
procedure ReadBinaryData(Stream: TStream);
procedure WriteBinaryData(Stream: TStream);
protected
procedure FocusChanged(Control: TWinControl); override;
function DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean; override;
function WantKey(Key: Integer; Shift: TShiftState;
const KeyText: WideString): Boolean; override;
procedure TextChanged; override;
procedure EnabledChanged; override;
procedure DefineProperties(Filer: TFiler); override;
{$IFDEF VCL}
procedure CreateParams(var Params: TCreateParams); override;
function GetPalette: HPALETTE; override;
{$ENDIF VCL}
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure Paint; override;
procedure DoOn; dynamic;
procedure DoOff; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ToggleSwitch;
published
{$IFDEF JVCLThemesEnabled}
property ParentBackground default True;
{$ENDIF JVCLThemesEnabled}
property Align;
property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone;
property Caption;
property Color;
property Cursor;
{$IFDEF VCL}
property DragCursor;
property DragKind;
property OnEndDock;
property OnStartDock;
{$ENDIF VCL}
property DragMode;
property Enabled;
property Font;
property GlyphOff: TBitmap index 0 read GetSwitchGlyph write SetSwitchGlyph stored StoreBitmap;
property GlyphOn: TBitmap index 1 read GetSwitchGlyph write SetSwitchGlyph stored StoreBitmap;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowFocus: Boolean read FShowFocus write SetShowFocus default True;
property ToggleKey: TShortCut read FToggleKey write FToggleKey default Ord(' ');
property ShowHint;
property StateOn: Boolean read FStateOn write SetStateOn default False;
property TabOrder;
property TabStop default True;
property TextPosition: TTextPos read FTextPosition write SetTextPosition default tpNone;
property Anchors;
property Constraints;
property Visible;
property OnClick;
property OnDblClick;
property OnEnter;
property OnExit;
property OnMouseMove;
property OnMouseDown;
property OnMouseUp;
property OnKeyDown;
property OnKeyUp;
property OnKeyPress;
property OnDragOver;
property OnDragDrop;
property OnEndDrag;
property OnStartDrag;
property OnContextPopup;
property OnOn: TNotifyEvent read FOnOn write FOnOn;
property OnOff: TNotifyEvent read FOnOff write FOnOff;
end;
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvSwitch.pas $';
Revision: '$Revision: 10612 $';
Date: '$Date: 2006-05-19 21:04:09 +0200 (ven., 19 mai 2006) $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
implementation
uses
JvJVCLUtils, JvThemes;
{$R JvSwitch.Res}
constructor TJvSwitch.Create(AOwner: TComponent);
var
I: Boolean;
begin
inherited Create(AOwner);
ControlStyle := [csClickEvents, csSetCaption, csCaptureMouse,
csOpaque, csDoubleClicks];
IncludeThemeStyle(Self, [csParentBackground]);
Width := 50;
Height := 60;
for I := False to True do
begin
FBitmaps[I] := TBitmap.Create;
SetSwitchGlyph(Ord(I), nil);
FBitmaps[I].OnChange := GlyphChanged;
end;
FUserBitmaps := [];
FShowFocus := True;
FStateOn := False;
FTextPosition := tpNone;
FBorderStyle := bsNone;
FToggleKey := Ord(' ');
TabStop := True;
end;
destructor TJvSwitch.Destroy;
var
I: Boolean;
begin
for I := False to True do
begin
FBitmaps[I].OnChange := nil;
FDisableBitmaps[I].Free;
FBitmaps[I].Free;
end;
inherited Destroy;
end;
{$IFDEF VCL}
procedure TJvSwitch.CreateParams(var Params: TCreateParams);
const
BorderStyles: array [TBorderStyle] of Longint = (0, WS_BORDER);
begin
inherited CreateParams(Params);
with Params do
begin
WindowClass.Style := WindowClass.Style or CS_HREDRAW or CS_VREDRAW;
Style := Style or Longword(BorderStyles[FBorderStyle]);
end;
end;
{$ENDIF VCL}
procedure TJvSwitch.DefineProperties(Filer: TFiler);
function DoWrite: Boolean;
begin
if Assigned(Filer.Ancestor) then
Result := FUserBitmaps <> TJvSwitch(Filer.Ancestor).FUserBitmaps
else
Result := FUserBitmaps <> [];
end;
begin
inherited DefineProperties(Filer);
Filer.DefineBinaryProperty('Data', ReadBinaryData, WriteBinaryData,DoWrite);
end;
{$IFDEF VCL}
function TJvSwitch.GetPalette: HPALETTE;
begin
if Enabled then
Result := FBitmaps[FStateOn].Palette
else
Result := 0;
end;
{$ENDIF VCL}
procedure TJvSwitch.ReadBinaryData(Stream: TStream);
begin
Stream.ReadBuffer(FUserBitmaps, SizeOf(FUserBitmaps));
end;
procedure TJvSwitch.WriteBinaryData(Stream: TStream);
begin
Stream.WriteBuffer(FUserBitmaps, SizeOf(FUserBitmaps));
end;
function TJvSwitch.StoreBitmap(Index: Integer): Boolean;
begin
Result := (Index <> 0) in FUserBitmaps;
end;
function TJvSwitch.GetSwitchGlyph(Index: Integer): TBitmap;
begin
if csLoading in ComponentState then
Include(FUserBitmaps, Index <> 0);
Result := FBitmaps[Index <> 0];
end;
procedure TJvSwitch.CreateDisabled(Index: Boolean);
begin
FreeAndNil(FDisableBitmaps[Index]);
FDisableBitmaps[Index] :=
CreateDisabledBitmap(FBitmaps[Index], clBlack);
end;
procedure TJvSwitch.GlyphChanged(Sender: TObject);
var
I: Boolean;
begin
for I := False to True do
if Sender = FBitmaps[I] then
CreateDisabled(I);
Invalidate;
end;
procedure TJvSwitch.SetSwitchGlyph(Index: Integer; Value: TBitmap);
const
ResName: array [Boolean] of PChar = ('JvSwitchOFF', 'JvSwitchON');
begin
if Value <> nil then
begin
FBitmaps[Index <> 0].Assign(Value);
Include(FUserBitmaps, Index <> 0);
end
else
begin
FBitmaps[Index <> 0].Assign(nil); // fixes GDI resource leak
FBitmaps[Index <> 0].LoadFromResourceName(HInstance, ResName[Index <> 0]);
Exclude(FUserBitmaps, Index <> 0);
end;
end;
procedure TJvSwitch.FocusChanged(Control: TWinControl);
var
Active: Boolean;
begin
Active := (Control = Self);
if Active <> FActive then
begin
FActive := Active;
if FShowFocus then
Invalidate;
end;
inherited FocusChanged(Control);
end;
procedure TJvSwitch.EnabledChanged;
begin
inherited EnabledChanged;
Invalidate;
end;
procedure TJvSwitch.TextChanged;
begin
inherited TextChanged;
Invalidate;
end;
function TJvSwitch.WantKey(Key: Integer; Shift: TShiftState;
const KeyText: WideString): Boolean;
begin
Result := IsAccel(Key, Caption) and CanFocus and (ssAlt in Shift);
if Result then
SetFocus;
end;
function TJvSwitch.DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean;
begin
Result := True; // the component paints the background in Paint
end;
procedure TJvSwitch.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
if Button = mbLeft then
begin
if TabStop and CanFocus then
SetFocus;
ToggleSwitch;
end;
inherited MouseDown(Button, Shift, X, Y);
end;
procedure TJvSwitch.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited KeyDown(Key, Shift);
if FToggleKey = ShortCut(Key, Shift) then
begin
ToggleSwitch;
Key := 0;
end;
end;
procedure TJvSwitch.Paint;
var
ARect: TRect;
Text: string;
FontHeight: Integer;
procedure DrawBitmap(Bmp: TBitmap);
var
IWidth, IHeight, X, Y: Integer;
IRect: TRect;
begin
IWidth := Bmp.Width;
IHeight := Bmp.Height;
IRect := Rect(0, 0, IWidth, IHeight);
X := 0;
Y := 0;
case FTextPosition of
tpNone:
begin
X := ((Width - IWidth) div 2);
Y := ((Height - IHeight) div 2);
end;
tpLeft:
begin
X := Width - IWidth;
Y := ((Height - IHeight) div 2);
Dec(ARect.Right, IWidth);
end;
tpRight:
begin
X := 0;
Y := ((Height - IHeight) div 2);
Inc(ARect.Left, IWidth);
end;
tpAbove:
begin
X := ((Width - IWidth) div 2);
Y := Height - IHeight;
Dec(ARect.Bottom, IHeight);
end;
tpBelow:
begin
X := ((Width - IWidth) div 2);
Y := 0;
Inc(ARect.Top, IHeight);
end;
end;
Bmp.Transparent := True;
Canvas.Draw(X, Y, Bmp);
if Focused and FShowFocus and TabStop and not (csDesigning in ComponentState) then
Canvas.DrawFocusRect(Rect(X, Y, X + IWidth, Y + IHeight));
end;
begin
ARect := GetClientRect;
{$IFDEF VisualCLX}
Canvas.Start;
try
{$ENDIF VisualCLX}
with Canvas do
begin
Font := Self.Font;
Brush.Color := Self.Color;
DrawThemedBackground(Self, Canvas, ARect);
if not Enabled and (FDisableBitmaps[FStateOn] <> nil) then
DrawBitmap(FDisableBitmaps[FStateOn])
else
DrawBitmap(FBitmaps[FStateOn]);
if FTextPosition <> tpNone then
begin
FontHeight := TextHeight('W');
with ARect do
begin
Top := ((Bottom + Top) - FontHeight) shr 1;
Bottom := Top + FontHeight;
end;
Text := Caption;
DrawText(Canvas, Text, Length(Caption), ARect,
DT_EXPANDTABS or DT_VCENTER or DT_CENTER);
end;
end;
{$IFDEF VisualCLX}
if BorderStyle = bsSingle then
begin
Canvas.Pen.Color := clBlack;
Canvas.Pen.Mode := pmCopy;
Canvas.Brush.Style := bsClear;
Canvas.Rectangle(ClientRect);
end;
finally
Canvas.Stop;
end;
{$ENDIF VisualCLX}
end;
procedure TJvSwitch.DoOn;
begin
if Assigned(FOnOn) then
FOnOn(Self);
end;
procedure TJvSwitch.DoOff;
begin
if Assigned(FOnOff) then
FOnOff(Self);
end;
procedure TJvSwitch.ToggleSwitch;
begin
StateOn := not StateOn;
end;
procedure TJvSwitch.SetBorderStyle(Value: TBorderStyle);
begin
if FBorderStyle <> Value then
begin
FBorderStyle := Value;
RecreateWnd;
end;
end;
procedure TJvSwitch.SetStateOn(Value: Boolean);
begin
if FStateOn <> Value then
begin
FStateOn := Value;
Invalidate;
if Value then
DoOn
else
DoOff;
end;
end;
procedure TJvSwitch.SetTextPosition(Value: TTextPos);
begin
if FTextPosition <> Value then
begin
FTextPosition := Value;
Invalidate;
end;
end;
procedure TJvSwitch.SetShowFocus(Value: Boolean);
begin
if FShowFocus <> Value then
begin
FShowFocus := Value;
if not (csDesigning in ComponentState) then
Invalidate;
end;
end;
{$IFDEF UNITVERSIONING}
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.