home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / RXSWITCH.PAS < prev    next >
Pascal/Delphi Source File  |  1999-10-12  |  13KB  |  458 lines

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