Rxswitch.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:12k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995 AO ROSNO                   }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9. unit RXSwitch;
  10. interface
  11. {$I RX.INC}
  12. uses SysUtils, {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  13.   Messages, Classes, Graphics, Controls, Forms, StdCtrls, ExtCtrls, Menus;
  14. type
  15. { TRxSwitch }
  16.   TTextPos = (tpNone, tpLeft, tpRight, tpAbove, tpBelow);
  17.   TSwitchBitmaps = set of Boolean;
  18.   TRxSwitch = class(TCustomControl)
  19.   private
  20.     FActive: Boolean;
  21.     FBitmaps: array[Boolean] of TBitmap;
  22.     FDisableBitmaps: array[Boolean] of TBitmap;
  23.     FOnOn: TNotifyEvent;
  24.     FOnOff: TNotifyEvent;
  25.     FStateOn: Boolean;
  26.     FTextPosition: TTextPos;
  27.     FBorderStyle: TBorderStyle;
  28.     FToggleKey: TShortCut;
  29.     FShowFocus: Boolean;
  30.     FUserBitmaps: TSwitchBitmaps;
  31.     procedure GlyphChanged(Sender: TObject);
  32.     procedure SetStateOn(Value: Boolean);
  33.     procedure SetTextPosition(Value: TTextPos);
  34.     procedure SetBorderStyle(Value: TBorderStyle);
  35.     function GetSwitchGlyph(Index: Integer): TBitmap;
  36.     procedure SetSwitchGlyph(Index: Integer; Value: TBitmap);
  37.     function StoreBitmap(Index: Integer): Boolean;
  38.     procedure SetShowFocus(Value: Boolean);
  39.     procedure CreateDisabled(Index: Integer);
  40.     procedure ReadBinaryData(Stream: TStream);
  41.     procedure WriteBinaryData(Stream: TStream);
  42.     procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
  43.     procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
  44.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  45.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  46.   protected
  47.     procedure CreateParams(var Params: TCreateParams); override;
  48.     procedure DefineProperties(Filer: TFiler); override;
  49.     function GetPalette: HPALETTE; override;
  50.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  51.       X, Y: Integer); override;
  52.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  53.     procedure Paint; override;
  54.     procedure DoOn; dynamic;
  55.     procedure DoOff; dynamic;
  56.   public
  57.     constructor Create(AOwner: TComponent); override;
  58.     destructor Destroy; override;
  59.     procedure ToggleSwitch;
  60.   published
  61.     property Align;
  62.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle
  63.       default bsNone;
  64.     property Caption;
  65.     property Color;
  66.     property Cursor;
  67.     property DragMode;
  68.     property DragCursor;
  69.     property Enabled;
  70.     property Font;
  71.     property GlyphOff: TBitmap index 0 read GetSwitchGlyph write SetSwitchGlyph
  72.       stored StoreBitmap;
  73.     property GlyphOn: TBitmap index 1 read GetSwitchGlyph write SetSwitchGlyph
  74.       stored StoreBitmap;
  75.     property ParentColor;
  76.     property ParentFont;
  77.     property ParentShowHint;
  78.     property PopupMenu;
  79.     property ShowFocus: Boolean read FShowFocus write SetShowFocus default True;
  80.     property ToggleKey: TShortCut read FToggleKey write FToggleKey
  81.       default VK_SPACE;
  82.     property ShowHint;
  83.     property StateOn: Boolean read FStateOn write SetStateOn default False;
  84.     property TabOrder;
  85.     property TabStop default True;
  86.     property TextPosition: TTextPos read FTextPosition write SetTextPosition
  87.       default tpNone;
  88. {$IFDEF RX_D4}
  89.     property Anchors;
  90.     property Constraints;
  91.     property DragKind;
  92. {$ENDIF}
  93.     property Visible;
  94.     property OnClick;
  95.     property OnDblClick;
  96.     property OnEnter;
  97.     property OnExit;
  98.     property OnMouseMove;
  99.     property OnMouseDown;
  100.     property OnMouseUp;
  101.     property OnKeyDown;
  102.     property OnKeyUp;
  103.     property OnKeyPress;
  104.     property OnDragOver;
  105.     property OnDragDrop;
  106.     property OnEndDrag;
  107. {$IFDEF WIN32}
  108.     property OnStartDrag;
  109. {$ENDIF}
  110. {$IFDEF RX_D5}
  111.     property OnContextPopup;
  112. {$ENDIF}
  113. {$IFDEF RX_D4}
  114.     property OnEndDock;
  115.     property OnStartDock;
  116. {$ENDIF}
  117.     property OnOn: TNotifyEvent read FOnOn write FOnOn;
  118.     property OnOff: TNotifyEvent read FOnOff write FOnOff;
  119.   end;
  120. implementation
  121. uses VCLUtils;
  122. {$IFDEF WIN32}
  123.  {$R *.R32}
  124. {$ELSE}
  125.  {$R *.R16}
  126. {$ENDIF}
  127. const
  128.   ResName: array [Boolean] of PChar = ('SWITCH_OFF', 'SWITCH_ON');
  129.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  130. { TRxSwitch component }
  131. constructor TRxSwitch.Create(AOwner: TComponent);
  132. var
  133.   I: Byte;
  134. begin
  135.   inherited Create(AOwner);
  136.   ControlStyle := [csClickEvents, csSetCaption, csCaptureMouse,
  137.     csOpaque, csDoubleClicks];
  138.   Width := 50;
  139.   Height := 60;
  140.   for I := 0 to 1 do begin
  141.     FBitmaps[Boolean(I)] := TBitmap.Create;
  142.     SetSwitchGlyph(I, nil);
  143.     FBitmaps[Boolean(I)].OnChange := GlyphChanged;
  144.   end;
  145.   FUserBitmaps := [];
  146.   FShowFocus := True;
  147.   FStateOn := False;
  148.   FTextPosition := tpNone;
  149.   FBorderStyle := bsNone;
  150.   FToggleKey := VK_SPACE;
  151.   TabStop := True;
  152. end;
  153. destructor TRxSwitch.Destroy;
  154. var
  155.   I: Byte;
  156. begin
  157.   for I := 0 to 1 do begin
  158.     FBitmaps[Boolean(I)].OnChange := nil;
  159.     FDisableBitmaps[Boolean(I)].Free;
  160.     FBitmaps[Boolean(I)].Free;
  161.   end;
  162.   inherited Destroy;
  163. end;
  164. procedure TRxSwitch.CreateParams(var Params: TCreateParams);
  165. begin
  166.   inherited CreateParams(Params);
  167.   with Params do begin
  168.     WindowClass.Style := WindowClass.Style or CS_HREDRAW or CS_VREDRAW;
  169.     Style := Style or Longword(BorderStyles[FBorderStyle]);
  170.   end;
  171. end;
  172. procedure TRxSwitch.DefineProperties(Filer: TFiler);
  173. {$IFDEF WIN32}
  174.   function DoWrite: Boolean;
  175.   begin
  176.     if Assigned(Filer.Ancestor) then
  177.       Result := FUserBitmaps <> TRxSwitch(Filer.Ancestor).FUserBitmaps
  178.     else Result := FUserBitmaps <> [];
  179.   end;
  180. {$ENDIF}
  181. begin
  182.   inherited DefineProperties(Filer);
  183.   Filer.DefineBinaryProperty('Data', ReadBinaryData, WriteBinaryData,
  184.     {$IFDEF WIN32} DoWrite {$ELSE} FUserBitmaps <> [] {$ENDIF});
  185. end;
  186. function TRxSwitch.GetPalette: HPALETTE;
  187. begin
  188.   if Enabled then Result := FBitmaps[FStateOn].Palette else Result := 0;
  189. end;
  190. procedure TRxSwitch.ReadBinaryData(Stream: TStream);
  191. begin
  192.   Stream.ReadBuffer(FUserBitmaps, SizeOf(FUserBitmaps));
  193. end;
  194. procedure TRxSwitch.WriteBinaryData(Stream: TStream);
  195. begin
  196.   Stream.WriteBuffer(FUserBitmaps, SizeOf(FUserBitmaps));
  197. end;
  198. function TRxSwitch.StoreBitmap(Index: Integer): Boolean;
  199. begin
  200.   Result := Boolean(Index) in FUserBitmaps;
  201. end;
  202. function TRxSwitch.GetSwitchGlyph(Index: Integer): TBitmap;
  203. begin
  204.   if csLoading in ComponentState then Include(FUserBitmaps, Boolean(Index));
  205.   Result := FBitmaps[Boolean(Index)]
  206. end;
  207. procedure TRxSwitch.CreateDisabled(Index: Integer);
  208. begin
  209.   if FDisableBitmaps[Boolean(Index)] <> nil then
  210.     FDisableBitmaps[Boolean(Index)].Free;
  211.   try
  212.     FDisableBitmaps[Boolean(Index)] :=
  213.       CreateDisabledBitmap(FBitmaps[Boolean(Index)], clBlack);
  214.   except
  215.     FDisableBitmaps[Boolean(Index)] := nil;
  216.     raise;
  217.   end;
  218. end;
  219. procedure TRxSwitch.GlyphChanged(Sender: TObject);
  220. var
  221.   I: Boolean;
  222. begin
  223.   for I := False to True do
  224.     if Sender = FBitmaps[I] then begin
  225.       CreateDisabled(Ord(I));
  226.     end;
  227.   Invalidate;
  228. end;
  229. procedure TRxSwitch.SetSwitchGlyph(Index: Integer; Value: TBitmap);
  230. begin
  231.   if Value <> nil then begin
  232.     FBitmaps[Boolean(Index)].Assign(Value);
  233.     Include(FUserBitmaps, Boolean(Index));
  234.   end
  235.   else begin
  236.     FBitmaps[Boolean(Index)].Handle := LoadBitmap(HInstance,
  237.       ResName[Boolean(Index)]);
  238.     Exclude(FUserBitmaps, Boolean(Index));
  239.   end;
  240. end;
  241. procedure TRxSwitch.CMFocusChanged(var Message: TCMFocusChanged);
  242. var
  243.   Active: Boolean;
  244. begin
  245.   with Message do Active := (Sender = Self);
  246.   if Active <> FActive then begin
  247.     FActive := Active;
  248.     if FShowFocus then Invalidate;
  249.   end;
  250.   inherited;
  251. end;
  252. procedure TRxSwitch.CMEnabledChanged(var Message: TMessage);
  253. begin
  254.   inherited;
  255.   Invalidate;
  256. end;
  257. procedure TRxSwitch.CMTextChanged(var Message: TMessage);
  258. begin
  259.   inherited;
  260.   Invalidate;
  261. end;
  262. procedure TRxSwitch.CMDialogChar(var Message: TCMDialogChar);
  263. begin
  264.   if IsAccel(Message.CharCode, Caption) and CanFocus then begin
  265.     SetFocus;
  266.     Message.Result := 1;
  267.   end;
  268. end;
  269. procedure TRxSwitch.MouseDown(Button: TMouseButton;
  270.   Shift: TShiftState; X, Y: Integer);
  271. begin
  272.   if Button = mbLeft then begin
  273.     if TabStop and CanFocus then SetFocus;
  274.     ToggleSwitch;
  275.   end;
  276.   inherited MouseDown(Button, Shift, X, Y);
  277. end;
  278. procedure TRxSwitch.KeyDown(var Key: Word; Shift: TShiftState);
  279. begin
  280.   inherited KeyDown(Key, Shift);
  281.   if FToggleKey = ShortCut(Key, Shift) then begin
  282.     ToggleSwitch;
  283.     Key := 0;
  284.   end;
  285. end;
  286. procedure TRxSwitch.Paint;
  287. var
  288.   ARect: TRect;
  289.   Text: array[0..255] of Char;
  290.   FontHeight: Integer;
  291.   procedure DrawBitmap(Bmp: TBitmap);
  292.   var
  293.     TmpImage: TBitmap;
  294.     IWidth, IHeight, X, Y: Integer;
  295.     IRect: TRect;
  296.   begin
  297.     IWidth := Bmp.Width;
  298.     IHeight := Bmp.Height;
  299.     IRect := Rect(0, 0, IWidth, IHeight);
  300.     TmpImage := TBitmap.Create;
  301.     try
  302.       TmpImage.Width := IWidth;
  303.       TmpImage.Height := IHeight;
  304.       TmpImage.Canvas.Brush.Color := Self.Brush.Color;
  305.       TmpImage.Canvas.BrushCopy(IRect, Bmp, IRect, Bmp.TransparentColor);
  306.       X := 0; Y := 0;
  307.       case FTextPosition of
  308.         tpNone:
  309.           begin
  310.             X := ((Width - IWidth) div 2);
  311.             Y := ((Height - IHeight) div 2);
  312.           end;
  313.         tpLeft:
  314.           begin
  315.             X := Width - IWidth;
  316.             Y := ((Height - IHeight) div 2);
  317.             Dec(ARect.Right, IWidth);
  318.           end;
  319.         tpRight:
  320.           begin
  321.             X := 0;
  322.             Y := ((Height - IHeight) div 2);
  323.             Inc(ARect.Left, IWidth);
  324.           end;
  325.         tpAbove:
  326.           begin
  327.             X := ((Width - IWidth) div 2);
  328.             Y := Height - IHeight;
  329.             Dec(ARect.Bottom, IHeight);
  330.           end;
  331.         tpBelow:
  332.           begin
  333.             X := ((Width - IWidth) div 2);
  334.             Y := 0;
  335.             Inc(ARect.Top, IHeight);
  336.           end;
  337.       end;
  338.       Canvas.Draw(X, Y, TmpImage);
  339.       if Focused and FShowFocus and TabStop and not (csDesigning in ComponentState) then
  340.         Canvas.DrawFocusRect(Rect(X, Y, X + IWidth, Y + IHeight));
  341.     finally
  342.       TmpImage.Free;
  343.     end;
  344.   end;
  345. begin
  346.   ARect := GetClientRect;
  347.   with Canvas do begin
  348.     Font := Self.Font;
  349.     Brush.Color := Self.Color;
  350.     FillRect(ARect);
  351.     if not Enabled and (FDisableBitmaps[FStateOn] <> nil) then
  352.       DrawBitmap(FDisableBitmaps[FStateOn])
  353.     else DrawBitmap(FBitmaps[FStateOn]);
  354.     if FTextPosition <> tpNone then begin
  355.       FontHeight := TextHeight('W');
  356.       with ARect do
  357.       begin
  358.         Top := ((Bottom + Top) - FontHeight) shr 1;
  359.         Bottom := Top + FontHeight;
  360.       end;
  361.       StrPCopy(Text, Caption);
  362. {$IFDEF WIN32}
  363.       Windows.DrawText(Handle, Text, StrLen(Text), ARect, DT_EXPANDTABS or
  364.         DT_VCENTER or DT_CENTER);
  365. {$ELSE}
  366.       WinProcs.DrawText(Handle, Text, StrLen(Text), ARect, DT_EXPANDTABS or
  367.         DT_VCENTER or DT_CENTER);
  368. {$ENDIF}
  369.     end;
  370.   end;
  371. end;
  372. procedure TRxSwitch.DoOn;
  373. begin
  374.   if Assigned(FOnOn) then FOnOn(Self);
  375. end;
  376. procedure TRxSwitch.DoOff;
  377. begin
  378.   if Assigned(FOnOff) then FOnOff(Self);
  379. end;
  380. procedure TRxSwitch.ToggleSwitch;
  381. begin
  382.   StateOn := not StateOn;
  383. end;
  384. procedure TRxSwitch.SetBorderStyle(Value: TBorderStyle);
  385. begin
  386.   if FBorderStyle <> Value then begin
  387.     FBorderStyle := Value;
  388.     RecreateWnd;
  389.   end;
  390. end;
  391. procedure TRxSwitch.SetStateOn(Value: Boolean);
  392. begin
  393.   if FStateOn <> Value then begin
  394.     FStateOn := Value;
  395.     Invalidate;
  396.     if Value then DoOn
  397.     else DoOff;
  398.   end;
  399. end;
  400. procedure TRxSwitch.SetTextPosition(Value: TTextPos);
  401. begin
  402.   if FTextPosition <> Value then begin
  403.     FTextPosition := Value;
  404.     Invalidate;
  405.   end;
  406. end;
  407. procedure TRxSwitch.SetShowFocus(Value: Boolean);
  408. begin
  409.   if FShowFocus <> Value then begin
  410.     FShowFocus := Value;
  411.     if not (csDesigning in ComponentState) then Invalidate;
  412.   end;
  413. end;
  414. end.