home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Vcl / DBOLECTL.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  7.0 KB  |  279 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Visual Component Library         }
  5. {                                                       }
  6. {       Copyright (c) 1999 Inprise Corporation          }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit DbOleCtl;
  11.  
  12. interface
  13.  
  14. uses Windows, Messages, SysUtils, Classes, Controls, Forms, OleCtrls, Db,
  15.   DbCtrls, ActiveX;
  16.  
  17. type
  18.   TDBOleControl = class;
  19.   TDataBindings = class;
  20.  
  21.   TDataBindItem = class(TCollectionItem)
  22.   private
  23.     FOwner: TDataBindings;
  24.     FDataLink: TFieldDataLink;
  25.     FDispId: TDispID;
  26.     procedure DataChange(Sender: TObject);
  27.     function GetDataField: string;
  28.     procedure SetDataField(const Value: string);
  29.     procedure SetDispID(Value: TDispID);
  30.     procedure UpdateData(Sender: TObject);
  31.   public
  32.     constructor Create(Collection: TCollection); override;
  33.     destructor Destroy; override;
  34.   published
  35.     property DataField: string read GetDataField write SetDataField;
  36.     property DispID: TDispID read FDispId write SetDispID;
  37.   end;
  38.  
  39.   TDataBindings = class(TCollection)
  40.   private
  41.     FDBOleControl: TDBOleControl;
  42.     function GetItem(Index: Integer): TDataBindItem;
  43.     procedure SetItem(Index: Integer; Value: TDataBindItem);
  44.   public
  45.     constructor Create(DBOleControl: TDBOleControl);
  46.     function Add: TDataBindItem;
  47.     procedure Update(Item: TCollectionItem); override;
  48.     function GetItemByDispID(ADispID: TDispID): TDataBindItem;
  49.     function GetOwner: TPersistent; override;
  50.     property Items[Index: Integer]: TDataBindItem read GetItem write SetItem; default;
  51.   end;
  52.  
  53.   TDBOleControl = class(TOleControl)
  54.   private
  55.     FDataBindings: TDataBindings;
  56.     FDataChanging: Boolean;
  57.     FDataSource: TDataSource;
  58.     procedure SetDataSource(Value: TDataSource);
  59.   protected
  60.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  61.     function OnChanged(dispid: TDispID): HResult; override;
  62.     function OnRequestEdit(dispid: TDispID): HResult; override;
  63.   public
  64.     constructor Create(AOwner: TComponent); override;
  65.     destructor Destroy; override;
  66.   published
  67.     property DataSource: TDataSource read FDataSource write SetDataSource;
  68.     property DataBindings: TDataBindings read FDataBindings write FDataBindings;
  69.  end;
  70.  
  71. implementation
  72.  
  73. { TDataBindItem }
  74.  
  75. constructor TDataBindItem.Create(Collection: TCollection);
  76. begin
  77.   inherited Create(Collection);
  78.   FOwner := Collection as TDataBindings;
  79.   FDataLink := TFieldDataLink.Create;
  80.   FDataLink.Control := FOwner.FDbOleControl;
  81.   FDataLink.OnDataChange := DataChange;
  82.   FDataLink.OnUpdateData := UpdateData;
  83. end;
  84.  
  85. procedure TDataBindItem.DataChange(Sender: TObject);
  86. var
  87.   LocalVar: OleVariant;
  88. begin
  89.   with FOwner.FDbOleControl do
  90.   begin
  91.     FDataChanging := True;
  92.     try
  93.       LocalVar := FDataLink.Field.Value;
  94.       if LocalVar <> Null then
  95.         SetProperty(FDispID, TVarData(LocalVar));
  96.     finally
  97.       FDataChanging := False;
  98.     end;
  99.   end;
  100. end;
  101.  
  102. destructor TDataBindItem.Destroy;
  103. begin
  104.   FDataLink.Free;
  105.   FDataLink := nil;
  106.   inherited Destroy;
  107. end;
  108.  
  109. function TDataBindItem.GetDataField: string;
  110. begin
  111.   Result := FDataLink.FieldName;
  112. end;
  113.  
  114. procedure TDataBindItem.SetDataField(const Value: string);
  115. begin
  116.   FDataLink.FieldName := Value;
  117.   Changed(False);
  118. end;
  119.  
  120. procedure TDataBindItem.SetDispID(Value: TDispID);
  121. begin
  122.   if Value <> FDispID then
  123.   begin
  124.     FDispID := Value;
  125.     Changed(False);
  126.   end;
  127. end;
  128.  
  129. procedure TDataBindItem.UpdateData(Sender: TObject);
  130. var
  131.   PropValue: OleVariant;
  132. begin
  133.   FOwner.FDbOleControl.GetProperty(FDispID, TVarData(PropValue));
  134.   FDataLink.Field.Value := PropValue;
  135. end;
  136.  
  137. { TDataBindings }
  138.  
  139. constructor TDataBindings.Create(DBOleControl: TDBOleControl);
  140. begin
  141.   inherited Create(TDataBindItem);
  142.   FDBOleControl:= DBOleControl;
  143. end;
  144.  
  145. function TDataBindings.Add: TDataBindItem;
  146. begin
  147.   Result:= TDataBindItem(inherited Add);
  148. end;
  149.  
  150. function TDataBindings.GetItem(index: integer): TDataBindItem;
  151. begin
  152.   Result:= TDataBindItem(inherited GetItem(Index));
  153. end;
  154.  
  155. function TDataBindings.GetItemByDispID(ADispID: TDispID): TDataBindItem;
  156. var
  157.   I: Integer;
  158. begin
  159.   Result := nil;
  160.   for I := 0 to Count - 1 do
  161.     if Items[I].DispID = ADispID then Result := Items[I];
  162. end;
  163.  
  164. function TDataBindings.GetOwner: TPersistent;
  165. begin
  166.   Result:=  FDBOleControl;
  167. end;
  168.  
  169. procedure TDataBindings.SetItem(index: integer; Value: TDataBindItem);
  170. begin
  171.   inherited SetItem(Index, Value);
  172. end;
  173.  
  174. procedure TDataBindings.Update(Item: TCollectionItem);
  175. begin
  176.  
  177. end;
  178.  
  179. { TDBOleControl }
  180.  
  181. constructor TDBOleControl.Create(AOwner: TComponent);
  182. begin
  183.   inherited Create(AOwner);
  184.   FDataBindings:= TDataBindings.Create(self);
  185. end;
  186.  
  187. destructor TDBOleControl.Destroy;
  188. begin
  189.   FDataBindings.Free;
  190.   inherited Destroy;
  191. end;
  192.  
  193. procedure TDBOleControl.Notification(AComponent: TComponent;
  194.   Operation: TOperation);
  195. begin
  196.   inherited Notification(AComponent, Operation);
  197.   if (Operation = opRemove) and (FDataSource <> nil) and
  198.     (AComponent = DataSource) then DataSource := nil;
  199. end;
  200.  
  201. function TDBOleControl.OnChanged(DispID: TDispID): HResult;
  202. var
  203.   Item: TDataBindItem;
  204.   I: Integer;
  205.  
  206.   procedure SetItemValue;
  207.   var
  208.     PropValue: OleVariant;
  209.   begin
  210.     if Item <> nil then
  211.     begin
  212.       GetProperty(Item.DispID, TVarData(PropValue));
  213.       if (Item.FDatalink <> nil) and (Item.FDatalink.Field <> nil) then
  214.       begin
  215.         Item.FDataLink.Edit;
  216.         Item.FDataLink.Field.Value := PropValue;
  217.       end;
  218.     end;
  219.   end;
  220.  
  221. begin
  222.   Result := S_OK;
  223.   try
  224.     if (not FDataChanging) and ([csLoading, csReading] * ComponentState = []) then
  225.     begin
  226.       if DispID = DISPID_UNKNOWN then
  227.       begin
  228.         for I := 0 to DataBindings.Count - 1 do
  229.         begin
  230.           Item := DataBindings[I];
  231.           SetItemValue;
  232.         end;
  233.       end
  234.       else begin
  235.         Item := DataBindings.GetItemByDispID(DispID);
  236.         SetItemValue;
  237.       end;
  238.     end;
  239.   except
  240.     // Return S_OK even in case of error
  241.   end;
  242. end;
  243.  
  244. function TDBOleControl.OnRequestEdit(DispID: TDispID): HResult;
  245. var
  246.   Item: TDataBindItem;
  247. begin
  248.   Result := S_OK;
  249.   try
  250.     if not FDataChanging then
  251.     begin
  252.       Item := DataBindings.GetItemByDispID(DispID);
  253.       if (Item <> nil) and not Item.FDataLink.CanModify then
  254.         Result := S_FALSE;
  255.     end;
  256.   except
  257.     Result := S_FALSE;  // Disallow edit if exception was raised
  258.   end;
  259. end;
  260.  
  261. procedure TDBOleControl.SetDataSource(Value: TDataSource);
  262. var
  263.   I: Integer;
  264. begin
  265.   if csLoading in ComponentState then
  266.     for I := 0 to DataBindings.Count - 1 do
  267.       if DataBindings[I].FDataLink.DataSourceFixed then Exit;
  268.   if Value = nil then DataBindings.Clear;
  269.   FDataSource := Value;
  270.   if Value <> nil then
  271.   begin
  272.     for I := 0 to DataBindings.Count - 1 do
  273.       DataBindings[I].FDataLink.DataSource := Value;
  274.     Value.FreeNotification(Self);
  275.   end;
  276. end;
  277.  
  278. end.
  279.