home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kolekce / d3456 / ALEXSOFT.ZIP / DBBOXGRD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-09-04  |  26.7 KB  |  857 lines

  1. (*////////////////////////////////////////////////////////////////////////////
  2. //   Part of AlexSoft VCL/DLL Library.                                      //
  3. //   All rights reserved. (c) Copyright 1998.                               //
  4. //   Created by: Alex Rabichooc                                             //
  5. //**************************************************************************//
  6. //  Users of this unit must accept this disclaimer of warranty:             //
  7. //    "This unit is supplied as is. The author disclaims all warranties,    //
  8. //    expressed or implied, including, without limitation, the warranties   //
  9. //    of merchantability and of fitness for any purpose.                    //
  10. //    The author assumes no liability for damages, direct or                //
  11. //    consequential, which may result from the use of this unit."           //
  12. //                                                                          //
  13. //  This Unit is donated to the public as public domain.                    //
  14. //                                                                          //
  15. //  This Unit can be freely used and distributed in commercial and          //
  16. //  private environments provided this notice is not modified in any way.   //
  17. //                                                                          //
  18. //  If you do find this Unit handy and you feel guilty for using such a     //
  19. //  great product without paying someone - sorry :-)                        //
  20. //                                                                          //
  21. //  Please forward any comments or suggestions to Alex Rabichooc at:        //
  22. //                                                                          //
  23. //  a_rabichooc@yahoo.com or alex@carmez.mldnet.com                         //
  24. /////////////////////////////////////////////////////////////////////////////*)
  25.  
  26. {---------------------------------------------------------------------------
  27.   TRaDBBox - Data-aware component like TDBCtrlGrid
  28.      properties
  29.         DataSource: TDataSource;
  30.            Defines DataSource of Component.
  31.         ShowBlobs: Boolean;
  32.            Determines whether Blob fileds will be shown automatically.
  33.         AllowDelete: Boolean;
  34.            Determines whether user can delete records from DataSet.
  35.         AllowInsert: Boolean;
  36.            Determines whether user can insert records into DataSet.
  37.         ConfirmDelete: Boolean;
  38.            Determines whether confirm dialog will be shown when user
  39.            will try to delete a record from the DataSet.
  40.         property ReadOnly: Boolean;
  41.            If this property is True then user can't modify the DataSet.
  42.         property CreateMode: TCreateMode;
  43.            cmAuto - The Component automatically will create editing fields.
  44.            cmManual - The User manually describes editing fields.
  45. ----------------------------------------------------------------------------}
  46.  
  47. unit dbBoxGrd;
  48.  
  49. interface
  50. uses Windows, Messages, SysUtils, Classes, Controls, Graphics, Forms,
  51.      DB, StdCtrls, DBCtrls, stdUtils;
  52.  
  53. type
  54.   TRaDBBox = class;
  55.  
  56.   TPanelDataLink = class(TDataLink)
  57.   private
  58.     FdbBoxGrid: TRaDBBox;
  59.   protected
  60.     procedure ActiveChanged; override;
  61.     procedure LayoutChanged; override;
  62.   end;
  63.  
  64.  
  65.   TRaDBBoxKey = (bgkNull, bgkEditMode, bgkPriorTab, bgkNextTab, bgkFirstTab,
  66.     bgkLastTab, bgkLeft, bgkRight, bgkUp, bgkDown, bgkScrollUp, bgkScrollDown,
  67.     bgkPageUp, bgkPageDown, bgkHome, bgkEnd, bgkInsert, bgkAppend, bgkDelete,
  68.     bgkEditButton);
  69.  
  70.   TCreateMode = (cmAuto, cmManual);
  71.   TOrientation = (orVertical, orHorizontal);
  72.   TRaDBBox = class(TScrollBox)
  73.   private
  74.     FRefreshing: Boolean;
  75.     FFixedFields: Boolean;
  76.     FAllowInsert: Boolean;
  77.     FAllowDelete: Boolean;
  78.     FConfirmDelete: Boolean;
  79.     FAllowMove: boolean;
  80.     FReadOnly: Boolean;
  81.     FCreateMode: TCreateMode;
  82.     FDataLink: TPanelDataLink;
  83.     FOrientation: TOrientation;
  84.     FLabelFont: TFont;
  85.     FOrigin: TPoint;
  86.     FShowBlobs: Boolean;
  87.     function CreateName(FName: String): String;
  88.     procedure CMChildKey(var Message: TCMChildKey); message CM_CHILDKEY;
  89.     procedure CNActiveChanged(var Message: TMessage); message CN_ACTIVECHANGED;
  90.     procedure CNCloseDBForm(var Message: TMessage); Message CN_CLOSEDBFORM;
  91.     function GetActualHeight: Integer;
  92.     function GetActualWidth: Integer;
  93.     function GetEditMode: Boolean;
  94.     procedure SetOrigin(Value: TPoint);
  95.     procedure SetOriginX(Value: Integer);
  96.     procedure SetOriginY(Value: Integer);
  97.     procedure SetReadOnly(Value: Boolean);
  98.     procedure SetEditMode(Value: Boolean);
  99.     procedure SetShowBlobs(Value: Boolean);
  100.   protected
  101.     function GetGridKey(var Key: Word; Shift: TShiftState): TRaDBBoxKey; virtual;
  102.     procedure DoExit; override;
  103.     function FindNext(StartControl: TWinControl; GoForward: Boolean;
  104.                                      var WrapFlag: Integer): TWinControl; virtual;
  105.     procedure Scroll(Inc: Integer);
  106.     procedure SelectNext(GoForward: Boolean);
  107.     procedure SelectLast;
  108.     procedure SetCreateMode(Value: TCreateMode);
  109.     function GetDataSource: TDataSource;
  110.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  111.     procedure Notification(AComponent: TComponent;
  112.                                           Operation: TOperation); override;
  113.     procedure RefreshFields; virtual;
  114.     procedure SetDataSource(Value: TDataSource); virtual;
  115.     procedure SetOrientation(Value: TOrientation); virtual;
  116.   public
  117.     constructor Create(AOwner: TComponent); override;
  118.     destructor Destroy; override;
  119.     procedure DoKey(Key: TRaDBBoxKey);
  120.     procedure StartRefresh;
  121.     procedure SetLabelFont(AFont: TFont);
  122.     procedure SetToActualHeight;
  123.     procedure SetToActualWidth;
  124.     property FixedFields: Boolean read FFixedFields write FFixedFields;
  125.     property EditMode: Boolean read GetEditMode write SetEditMode;
  126.     property ActualHeight: Integer read GetActualHeight;
  127.     property ActualWidth: Integer read GetActualWidth;
  128.     property Refreshing: boolean read FRefreshing;
  129.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  130.   published
  131.     property ShowBlobs: Boolean read FShowBlobs write SetShowBlobs;
  132.     property AllowDelete: Boolean read FAllowDelete write FAllowDelete default True;
  133.     property AllowInsert: Boolean read FAllowInsert write FAllowInsert default True;
  134.     property AllowMove: Boolean read FAllowMove write FAllowMove default True;
  135.     property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True;
  136.     property ReadOnly: Boolean read FReadOnly write SetReadOnly;
  137.     property Orientation: TOrientation read FOrientation write SetOrientation;
  138.     property CreateMode: TCreateMode read FCreateMode write SetCreateMode;
  139.     property OriginX: integer read FOrigin.X write SetOriginX;
  140.     property OriginY: integer read FOrigin.Y write SetOriginY;
  141.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  142.     property Font;
  143.     property LabelFont: TFont read FLabelFont write SetLabelFont;
  144.     property OnKeyDown;
  145.     property OnKeyPress;
  146.     property OnKeyUp;
  147.   end;
  148.  
  149. implementation
  150.  
  151. uses grids, dbEdFld, Dialogs, DbConsts, dbTools, DbXCnsts;
  152.  
  153. {TPanelDataLink}
  154. procedure TPanelDataLink.ActiveChanged;
  155. begin
  156.   if (FdbBoxGrid <> nil) then
  157.       FdbBoxGrid.StartRefresh;
  158. end;
  159.  
  160. procedure TPanelDataLink.LayoutChanged;
  161. begin
  162.   Inherited LayoutChanged;
  163.   if (FdbBoxGrid <> nil) then
  164.       FdbBoxGrid.StartRefresh;
  165. end;
  166.  
  167. {TRaDBBox}
  168. constructor TRaDBBox.Create(AOwner: TComponent);
  169. begin
  170.    Inherited Create(AOwner);
  171.    FDataLink := TPanelDataLink.Create;
  172.    FDataLink.FdbBoxGrid := Self;
  173.    FLabelFont := TFont.Create;
  174.    Height := 100;
  175.    Inherited TabStop := False;
  176.    FAllowInsert := True;
  177.    FAllowDelete := True;
  178.    FConfirmDelete := True;
  179.    FAllowMove := True;
  180.    FOrigin.X := 10;
  181.    FOrigin.Y := 10;
  182. end;
  183.  
  184. destructor TRaDBBox.Destroy;
  185. begin
  186.    FDataLink.Free;
  187.    FDataLink := nil;
  188.    if FLabelFont <> nil then
  189.       FLabelFont.Free;
  190.    Inherited Destroy;
  191. end;
  192.  
  193. function TRaDBBox.GetDataSource: TDataSource;
  194. begin
  195.    Result := FDataLink.DataSource;
  196. end;
  197.  
  198. procedure TRaDBBox.Notification(AComponent: TComponent;
  199.                                                       Operation: TOperation);
  200. begin
  201.   inherited Notification(AComponent, Operation);
  202.   if (Operation = opRemove) and (FDataLink <> nil) and
  203.      (AComponent = DataSource) then
  204.       DataSource := nil;
  205. end;
  206.  
  207. function TRaDBBox.CreateName(FName: String): String;
  208. var i: Integer;
  209.     AName: String;
  210. begin
  211.    AName := Format('%s', [FName]);
  212.    i := 0;
  213.    while Owner.FindComponent(AName) <> nil do
  214.    begin
  215.       inc(i);
  216.       AName := Format('%s%d', [FName,i]);
  217.    end;
  218.    for i := 1 to Length(AName) do
  219.      if not (AName[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_']) then
  220.        AName[i] := '_';
  221.    Result := AName;
  222. end;
  223.  
  224. procedure TRaDBBox.RefreshFields;
  225.  
  226.   procedure RemoveFields;
  227.   begin
  228.      while ComponentCount > 0 do
  229.         Components[0].Free;
  230.   end;
  231.  
  232.   procedure CreateFields;
  233.   var i: Integer;
  234.       Field: TField;
  235.       DBEditField: TRaDBEdit;
  236.       ATop, ALeft, AWidth, AHeight, LineHeight, LineDistance: integer;
  237.       AVisible: Boolean;
  238.       MaxLabelLength: Integer;
  239.   begin
  240.      LineDistance := 10;
  241.      if not FDataLink.Active then
  242.         exit;
  243.      AVisible := Visible;
  244.      try
  245.         Visible := False;
  246.         ATop := FOrigin.Y;
  247.         ALeft := FOrigin.X;
  248.         MaxLabelLength := 0;
  249.         LineHeight := 0;
  250.         for i := 0 to FDataLink.DataSet.FieldCount - 1  do
  251.         begin
  252.            Field := FDataLink.DataSet.Fields[i];
  253.            if(Field.Visible) then
  254.            begin
  255.               DBEditField := TRaDBEdit.Create(Self);
  256.               DBEditField.Parent := Self;
  257.               DBEditField.ShowBlob := FShowBlobs;
  258.               DBEditField.DataSource := DataSource;
  259.               DBEditField.DataField := Field.FieldName;
  260.               DBEditField.TabStop :=
  261.                    not (Field.ReadOnly or
  262.                            (Field.FieldKind in [fkCalculated, fkInternalCalc]));
  263.               if ReadOnly then
  264.               begin
  265.                  if DBEditField.EditKind = ekControl then
  266.                      DBEditField.EditKind := ekCommon;
  267.                  if DBEditField.FieldType = efLookUp then
  268.                      DBEditField.EditKind := ekView;
  269.               end;
  270.               DBEditField.Name := CreateName('df'+Field.FieldName);
  271.               DBEditField.Top := ATop;
  272.               DBEditField.Left := ALeft;
  273.               DBEditField.Font := Font;
  274.               if DBEditField.EditKind = ekView then
  275.               begin
  276.                 DBEditField.Font.Style := [fsBold];
  277.                 DBEditField.Font.Color := clNavy;
  278.               end;
  279.               DBEditField.LabelFont := FLabelFont;
  280.               if Orientation = orVertical then
  281.               begin
  282.                  DBEditField.DistanceX := 8;
  283.                  if MaxLabelLength < DBEditField.CLabel.Width then
  284.                     MaxLabelLength := DBEditField.CLabel.Width;
  285.                  if ComponentCount > 1 then
  286.                  begin
  287.                     ATop := ATop+LineDistance;
  288.                     if ComponentCount > 1 then
  289.                         Inc(ATop,
  290.                            (Components[ComponentCount-2] as TControl).Height);
  291.                     DBEditField.Left := ALeft;
  292.                     DBEditField.Top := ATop;
  293.                  end;
  294.               end
  295.                 else
  296.                 if ComponentCount > 1 then
  297.                 begin
  298.                    ATop := (Components[ComponentCount-2] as TControl).Top;
  299.                    ALeft := (Components[ComponentCount-2] as TControl).Left;
  300.                    AWidth := (Components[ComponentCount-2] as TControl).Width;
  301.                    AHeight := (Components[ComponentCount-2] as TControl).Height;
  302.                    if LineHeight < AHeight+LineDistance then
  303.                            LineHeight := AHeight+LineDistance;
  304.                    if ALeft + AWidth + LineDistance + DbEditField.Width >
  305.                             Self.ClientWidth-GetSystemMetrics(SM_CXVSCROLL) then
  306.                    begin
  307.                       ALeft := FOrigin.X;
  308.                       ATop := ATop + LineHeight;
  309.                    end
  310.                      else
  311.                         ALeft := ALeft + AWidth + LineDistance;
  312.                    DBEditField.Top := ATop;
  313.                    DBEditField.Left := ALeft;
  314.                 end;
  315.            end;
  316.        end;
  317.        if Orientation = orVertical then
  318.        begin
  319.            i := 0;
  320.            while i < ComponentCount do
  321.            begin
  322.               DBEditField := Components[i] as TRaDBEdit;
  323.               DBEditField.DistanceX :=
  324.                                 8 + MaxLabelLength - DBEditField.CLabel.Width;
  325.               inc(i);
  326.            end;
  327.        end;
  328.       finally
  329.        Visible := AVisible;
  330.      end;
  331.   end;
  332.  
  333. begin
  334.    if (CreateMode = cmAuto) and not FFixedFields then
  335.    begin
  336.       RemoveFields;
  337.       CreateFields;
  338.    end;
  339. end;
  340.  
  341. procedure TRaDBBox.SetOrientation(Value: TOrientation);
  342. begin
  343.    if Value <> FOrientation then
  344.    begin
  345.       FOrientation := Value;
  346.       StartRefresh;
  347.    end;
  348. end;
  349.  
  350. procedure TRaDBBox.StartRefresh;
  351. begin
  352.   if not FRefreshing then
  353.   begin
  354.      FRefreshing := True;
  355.      PostMessage(Handle, CN_ACTIVECHANGED, 0, 0);
  356.   end;
  357. end;
  358.  
  359. procedure TRaDBBox.CMChildKey(var Message: TCMChildKey);
  360. var
  361.   GridKey: TRaDBBoxKey;
  362. begin
  363.   with Message do
  364.     if Sender <> Self then
  365.     begin
  366.       GridKey := GetGridKey(CharCode, GetShiftState);
  367.       if Assigned(OnKeyDown) then OnKeyDown(Sender, CharCode, GetShiftState);
  368.       if (GridKey <> bgkNull) or ReadOnly then
  369.       begin
  370.         DoKey(GridKey);
  371.         Result := 1;
  372.         Exit;
  373.       end;
  374.     end;
  375.   inherited;
  376. end;
  377.  
  378. procedure TRaDBBox.CNActiveChanged(var Message: TMessage);
  379. begin
  380.    RefreshFields;
  381.    FRefreshing := False;
  382. end;
  383.  
  384. procedure TRaDBBox.CNCloseDBForm(var Message: TMessage);
  385. begin
  386.    if (DataSource <> nil) and
  387.       (DataSource.DataSet <> nil) then
  388.      if Message.WParam = mrCancel then
  389.         DataSource.DataSet.Cancel
  390.        else
  391.         DataSource.DataSet.CheckBrowseMode;
  392. end;
  393.  
  394. procedure TRaDBBox.DoExit;
  395. begin
  396.    if (DataSource <> nil) and
  397.       (DataSource.DataSet <> nil) and
  398.       (DataSource.DataSet.Modified) then
  399.      DataSource.DataSet.Post;
  400.    Inherited DoExit;
  401. end;
  402.  
  403. function TRaDBBox.FindNext(StartControl: TWinControl;
  404.  GoForward: Boolean; var WrapFlag: Integer): TWinControl;
  405. var
  406.   I, StartIndex: Integer;
  407.   List: TList;
  408. begin
  409.   List := TList.Create;
  410.   try
  411.     StartIndex := 0;
  412.     I := 0;
  413.     Result := StartControl;
  414.     GetTabOrderList(List);
  415.     if List.Count > 0 then
  416.     begin
  417.       StartIndex := List.IndexOf(StartControl);
  418.       if StartIndex = -1 then
  419.         if GoForward then
  420.           StartIndex := List.Count - 1 else
  421.           StartIndex := 0;
  422.       I := StartIndex;
  423.       repeat
  424.         if GoForward then
  425.         begin
  426.           Inc(I);
  427.           if I = List.Count then I := 0;
  428.         end else
  429.         begin
  430.           if I = 0 then I := List.Count;
  431.           Dec(I);
  432.         end;
  433.         Result := List[I];
  434.       until (Result.CanFocus and Result.TabStop) or (I = StartIndex);
  435.     end;
  436.     WrapFlag := 0;
  437.     if GoForward then
  438.     begin
  439.       if I <= StartIndex then WrapFlag := 1;
  440.     end else
  441.     begin
  442.       if I >= StartIndex then WrapFlag := -1;
  443.     end;
  444.   finally
  445.     List.Free;
  446.   end;
  447. end;
  448.  
  449. function TRaDBBox.GetActualHeight: Integer;
  450. var i: Integer;
  451. begin
  452.    Result := 0;
  453.    for i := 0 to ControlCount - 1 do
  454.      if Result < Controls[i].Top + Controls[i].Height then
  455.          Result := Controls[i].Top + Controls[i].Height;
  456.    if BorderStyle <> bsNone then
  457.       Inc(Result, 2);
  458. end;
  459.  
  460. function TRaDBBox.GetActualWidth: Integer;
  461. var i: Integer;
  462. begin
  463.    Result := 0;
  464.    for i := 0 to ControlCount - 1 do
  465.      if Result < Controls[i].Left + Controls[i].Width then
  466.          Result := Controls[i].Left + Controls[i].Width;
  467.    if BorderStyle <> bsNone then
  468.       Inc(Result, 2);
  469. end;
  470.  
  471. function TRaDBBox.GetEditMode: Boolean;
  472. begin
  473.   Result := not Focused and ContainsControl(FindControl(GetFocus));
  474. end;
  475.  
  476. procedure TRaDBBox.KeyDown(var Key: Word; Shift: TShiftState);
  477. begin
  478.   inherited KeyDown(Key, Shift);
  479.   DoKey(GetGridKey(Key, Shift));
  480. end;
  481.  
  482. function TRaDBBox.GetGridKey(var Key: Word; Shift: TShiftState): TRaDBBoxKey;
  483. var
  484.   GridKey: TRaDBBoxKey;
  485.   ParentForm: TCustomForm;
  486.   IsLookup: Boolean;
  487. begin
  488.    IsLookup := false;
  489.    ParentForm := GetParentForm(Self);
  490.    if (ParentForm <> nil) and
  491.       (ParentForm.ActiveControl <> nil) and
  492.       (ParentForm.ActiveControl is TxDBLookUpComboBox) then
  493.       IsLookup := (ParentForm.ActiveControl as TxDBLookUpComboBox).ListVisible;
  494.   GridKey := bgkNull;
  495.   if not (ParentForm.ActiveControl is TCustomGrid) then
  496.   case Key of
  497.     VK_F1: if Shift = [ssCtrl] then
  498.                 GridKey := bgkEditButton;
  499.     VK_LEFT: if (ssCtrl in Shift) then
  500.                 GridKey := bgkFirstTab;
  501.     VK_RIGHT: if (ssCtrl in Shift) then
  502.                 GridKey := bgkLastTab;
  503.     VK_UP: if (Shift = []) and not IsLookup then GridKey := bgkUp;
  504.     VK_DOWN: if (Shift = [])and not IsLookup then GridKey := bgkDown;
  505.     VK_PRIOR: if not IsLookup then
  506.                 if ssCtrl in Shift then
  507.                    GridKey := bgkHome
  508.                   else
  509.                    GridKey := bgkPageUp;
  510.     VK_NEXT: if not IsLookup then
  511.                if ssCtrl in Shift then
  512.                   GridKey := bgkEnd
  513.                  else
  514.                   GridKey := bgkPageDown;
  515.     VK_HOME: if ssCtrl in Shift then
  516.                GridKey := bgkHome;
  517.     VK_END: if ssCtrl in Shift then
  518.                GridKey := bgkEnd;
  519.     VK_RETURN:
  520.         if (Shift = []) and not IsLookup then
  521.            GridKey := bgkNextTab;
  522.     VK_TAB:
  523.       if not (ssCtrl in Shift) then
  524.         if ssShift in Shift then
  525.           GridKey := bgkPriorTab else
  526.           GridKey := bgkNextTab;
  527.     VK_F2: GridKey := bgkEditMode;
  528.     VK_INSERT:
  529.       if GetKeyState(VK_CONTROL) >= 0 then
  530.         GridKey := bgkInsert else
  531.         GridKey := bgkAppend;
  532.     VK_DELETE: if GetKeyState(VK_CONTROL) < 0 then GridKey := bgkDelete;
  533.     VK_F8: GridKey := bgkDelete;
  534.   end;
  535.   Result := GridKey;
  536. end;
  537.  
  538. procedure TRaDBBox.SetEditMode(Value: Boolean);
  539. var
  540.   Control: TWinControl;
  541. begin
  542.   if GetEditMode <> Value then
  543.     if Value then
  544.     begin
  545.       Control := FindNextControl(nil, True, True, False);
  546.       if Control <> nil then Control.SetFocus;
  547.     end else
  548.       SetFocus;
  549. end;
  550.  
  551. procedure TRaDBBox.SetOriginX(Value: Integer);
  552. var NewOrigin: TPoint;
  553. begin
  554.    NewOrigin.X := Value;
  555.    NewOrigin.Y := FOrigin.Y;
  556.    SetOrigin(NewOrigin);
  557. end;
  558.  
  559. procedure TRaDBBox.SetOriginY(Value: Integer);
  560. var NewOrigin: TPoint;
  561. begin
  562.    NewOrigin.X := FOrigin.X;
  563.    NewOrigin.Y := Value;
  564.    SetOrigin(NewOrigin);
  565. end;
  566.  
  567. procedure TRaDBBox.SetOrigin(Value: TPoint);
  568. begin
  569.    if (Value.x <> FOrigin.x) or (Value.y <> FOrigin.y) then
  570.    begin
  571.       FOrigin := Value;
  572.       StartRefresh;
  573.    end;
  574. end;
  575.  
  576. procedure TRaDBBox.SetReadOnly(Value: Boolean);
  577. begin
  578.    if (Value <> FReadOnly) then
  579.       if (CreateMode = cmAuto) then
  580.    begin
  581.       FReadOnly := Value;
  582.       TabStop := FReadOnly;
  583.       StartRefresh;
  584.    end
  585.      else
  586.        Raise Exception.Create(SCantChangeReadOnly);
  587. end;
  588.  
  589. procedure TRaDBBox.SetToActualHeight;
  590. begin
  591.    Height := ActualHeight;
  592. end;
  593.  
  594. procedure TRaDBBox.SetToActualWidth;
  595. begin
  596.    Width := ActualWidth;
  597. end;
  598.  
  599. procedure TRaDBBox.Scroll(Inc: Integer);
  600. begin
  601.   if FDataLink.Active and (Inc <> 0) then
  602.     with FDataLink.DataSet do
  603.       if State = dsInsert then
  604.       begin
  605.         UpdateRecord;
  606.         if Modified then
  607.         begin
  608.           DisableControls;
  609.           try
  610.              Post;
  611.              if (Inc > 0) and FAllowInsert and FAllowMove then
  612.                   Append;
  613.           finally
  614.              EnableControls;
  615.           end;
  616.         end
  617.           else
  618.           if (Inc < 0) or not EOF then Cancel;
  619.       end else
  620.       begin
  621.         CheckBrowseMode;
  622.         DisableControls;
  623.         try
  624.           if FAllowMove then
  625.              MoveBy(Inc);
  626.           if (Inc = 1) and EOF and CanModify and FAllowInsert and FAllowMove then
  627.              Append;
  628.         finally
  629.           EnableControls;
  630.         end;
  631.       end;
  632. end;
  633.  
  634. procedure TRaDBBox.SetDataSource(Value: TDataSource);
  635. begin
  636.    if (Value <> FDataLink.DataSource) and
  637.       ((FDataLink.DataSet = nil) or (FCreateMode = cmAuto)) then
  638.    begin
  639.       FDataLink.DataSource := Value;
  640.       if Value <> nil then Value.FreeNotification(Self);
  641.    end
  642.     else
  643.      if (FCreateMode <> cmAuto) and (Value <> FDataLink.DataSource) then
  644.        Raise Exception.Create(SCantChangeDataSource);
  645. end;
  646.  
  647. procedure TRaDBBox.DoKey(Key: TRaDBBoxKey);
  648. var ParentForm: TCustomForm;
  649. begin
  650.   if FDataLink.Active then
  651.   begin
  652.     with FDataLink.DataSet do
  653.       case Key of
  654.         bgkEditMode: EditMode := not EditMode;
  655.         bgkPriorTab: SelectNext(False);
  656.         bgkNextTab: SelectNext(True);
  657.         bgkFirstTab:
  658.                 begin
  659.                    EditMode := False;
  660.                    EditMode := True;
  661.                 end;
  662.         bgkLastTab: SelectLast;
  663.         bgkUp: SelectNext(False);
  664.         bgkDown: SelectNext(True);
  665.         bgkScrollUp: Scroll(-1);
  666.         bgkScrollDown: Scroll(1);
  667.         bgkPageUp: Scroll(-1);
  668.         bgkPageDown: Scroll(1);
  669.         bgkHome: if FAllowMove then First;
  670.         bgkEnd:  if FAllowMove then Last;
  671.         bgkInsert:
  672.           if CanModify and FAllowInsert and FAllowMove then
  673.           begin
  674.             Insert;
  675.             EditMode := True;
  676.           end;
  677.         bgkAppend:
  678.           if CanModify and FAllowInsert and FAllowMove then
  679.           begin
  680.             Append;
  681.             EditMode := True;
  682.           end;
  683.         bgkDelete:
  684.           if CanModify and FAllowDelete and not ReadOnly and
  685.              (not FConfirmDelete or
  686.                     (MessageDlg(SDeleteRecordQuestion, mtConfirmation,
  687.                                                mbOKCancel, 0) <> idCancel)) then
  688.             Delete;
  689.         bgkEditButton:
  690.             begin
  691.                ParentForm := GetParentForm(Self);
  692.                if (ParentForm <> nil) and
  693.                   (ParentForm.ActiveControl <> nil) and
  694.                   (ParentForm.ActiveControl.Parent is TRaDBEdit) then
  695.                   (ParentForm.ActiveControl.Parent as TRaDBEdit).ClickButton;
  696.             end;
  697.       end;
  698.   end;
  699. end;
  700.  
  701. procedure TRaDBBox.SelectLast;
  702. var
  703.   ParentForm: TCustomForm;
  704.   ActiveControl, Control: TWinControl;
  705.   WrapFlag: Integer;
  706. begin
  707.   ParentForm := GetParentForm(Self);
  708.   if ParentForm <> nil then
  709.   begin
  710.     EditMode := False;
  711.     EditMode := True;
  712.     ActiveControl := ParentForm.ActiveControl;
  713.     if ContainsControl(ActiveControl) then
  714.     begin
  715.       Control := FindNext(ActiveControl, False, WrapFlag);
  716.       Control.SetFocus;
  717.     end;
  718.   end;
  719. end;
  720.  
  721. procedure TRaDBBox.SelectNext(GoForward: Boolean);
  722. var
  723.   ParentForm: TCustomForm;
  724.   ActiveControl, Control: TWinControl;
  725.   WrapFlag: Integer;
  726. begin
  727.   ParentForm := GetParentForm(Self);
  728.   if ParentForm <> nil then
  729.   begin
  730.     ActiveControl := ParentForm.ActiveControl;
  731.     if ContainsControl(ActiveControl) then
  732.     begin
  733.       Control := FindNext(ActiveControl, GoForward, WrapFlag);
  734.       if not (FDataLink.DataSet.State in dsEditModes) then
  735.         SetFocus;
  736.       try
  737.         if WrapFlag <> 0 then Scroll(WrapFlag);
  738.       except
  739.         ActiveControl.SetFocus;
  740.         raise;
  741.       end;
  742.       if not Control.CanFocus then
  743.         Control := FindNext(Control, GoForward, WrapFlag);
  744.       Control.SetFocus;
  745.     end;
  746.   end;
  747. end;
  748.  
  749. procedure TRaDBBox.SetCreateMode(Value: TCreateMode);
  750.  
  751.    procedure SetOwnerToForm;
  752.    var AField, NewField: TRaDBEdit;
  753.        AName, ADataField: String;
  754.        ADataSource: TDataSource;
  755.        AVisible: boolean;
  756.        ABounds: TRect;
  757.        AEditKind: TEditKind;
  758.        ParentForm: TCustomForm;
  759.    begin
  760.      ParentForm := GetParentForm(Self);
  761.      if ParentForm = nil then
  762.        exit;
  763.      AVisible := Visible;
  764.      try
  765.         Visible := False;
  766.         while ComponentCount > 0 do
  767.         begin
  768.            AField := Components[0] as TRaDBEdit;
  769.            ABounds.Left := AField.Left;
  770.            ABounds.Right := AField.Width;
  771.            ABounds.Top := AField.Top;
  772.            ABounds.Bottom := AField.Height;
  773.            AName := CreateName(AField.Name);
  774.            NewField := TRaDBEdit.Create(ParentForm);
  775.            NewField.DistanceX := AField.DistanceX;
  776.            NewField.DistanceY := AField.DistanceY;
  777.            NewField.ShowBlob := AField.ShowBlob;
  778.            NewField.Font := AField.Font;
  779.            NewField.LabelFont := AField.LabelFont;
  780.            ADataField := AField.DataField;
  781.            ADataSource := AField.DataSource;
  782.            NewField.TabStop := AField.TabStop;;
  783.            AEditKind :=AField.EditKind;
  784.            NewField.Parent := Self;
  785.            AField.Free;
  786.            NewField.Name := AName;
  787.            NewField.DataField := ADataField;
  788.            NewField.DataSource := ADataSource;
  789.            NewField.EditKind := AEditKind;
  790.            NewField.SetBounds(ABounds.Left,ABounds.Top,
  791.                                   ABounds.Right,ABounds.Bottom);
  792.  
  793.         end;
  794.      finally
  795.         Visible := AVisible;
  796.      end;
  797.    end;
  798.  
  799.    procedure RemoveControls;
  800.    begin
  801.      while ControlCount > 0 do
  802.         Controls[0].Free;
  803.    end;
  804.  
  805. var AVisible: boolean;
  806. begin
  807.    if Value <> FCreateMode then
  808.    begin
  809.       FCreateMode := Value;
  810.       case FCreateMode of
  811.          cmAuto:
  812.              begin
  813.                 AVisible := Visible;
  814.                 try
  815.                   Visible := False;
  816.                   RemoveControls;
  817.                   StartRefresh;
  818.                 finally
  819.                   Visible := AVisible;
  820.                 end;
  821.              end;
  822.          cmManual:
  823.              SetOwnerToForm;
  824.       end;
  825.    end;
  826. end;
  827.  
  828. procedure TRaDBBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  829. var MustRefresh: Boolean;
  830. begin
  831.    MustRefresh := (FDataLink <> nil) and (AWidth <> Width) and
  832.                   (CreateMode = cmAuto) and (FOrientation = orHorizontal);
  833.    inherited SetBounds(ALeft, ATop, AWidth, AHeight);
  834.    if MustRefresh then
  835.       StartRefresh;
  836. end;
  837.  
  838. procedure TRaDBBox.SetLabelFont(AFont: TFont);
  839. begin
  840.    if (AFont <> nil) then
  841.    begin
  842.       FLabelFont.Assign(AFont);
  843.       StartRefresh;
  844.    end;
  845. end;
  846.  
  847. procedure TRaDBBox.SetShowBlobs(Value: Boolean);
  848. begin
  849.    if Value <> FShowBlobs then
  850.    begin
  851.       FShowBlobs := Value;
  852.       StartRefresh;
  853.    end;
  854. end;
  855.  
  856. end.
  857.