home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 June / Chip_2002-06_cd1.bin / zkuste / delphi / kolekce / d6 / rxlibsetup.exe / {app} / units / RXSWITCH.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-02-19  |  12.3 KB  |  460 lines

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