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

Delphi控件源码

开发平台:

Delphi

  1.   inherited Destroy;
  2. end;
  3. procedure TbsNavButton.GetSkinData;
  4. begin
  5.   inherited;
  6.   MaskPicture := nil;
  7. end;
  8. procedure TbsNavButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  9.   X, Y: Integer);
  10. begin
  11.   inherited MouseDown (Button, Shift, X, Y);
  12.   if nsAllowTimer in FNavStyle then
  13.   begin
  14.     if FRepeatTimer = nil then
  15.       FRepeatTimer := TTimer.Create(Self);
  16.     FRepeatTimer.OnTimer := TimerExpired;
  17.     FRepeatTimer.Interval := InitRepeatPause;
  18.     FRepeatTimer.Enabled  := True;
  19.   end;
  20. end;
  21. procedure TbsNavButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  22.                                   X, Y: Integer);
  23. begin
  24.   inherited MouseUp (Button, Shift, X, Y);
  25.   if FRepeatTimer <> nil then
  26.     FRepeatTimer.Enabled  := False;
  27. end;
  28. procedure TbsNavButton.TimerExpired(Sender: TObject);
  29. begin
  30.   FRepeatTimer.Interval := RepeatPause;
  31.   if (FMouseIn and FDown) and MouseCapture then
  32.   begin
  33.     try
  34.       ButtonClick;
  35.     except
  36.       FRepeatTimer.Enabled := False;
  37.       raise;
  38.     end;
  39.   end;
  40. end;
  41. { TbsNavDataLink }
  42. constructor TbsNavDataLink.Create(ANav: TbsSkinDBNavigator);
  43. begin
  44.   inherited Create;
  45.   FNavigator := ANav;
  46.   VisualControl := True;
  47. end;
  48. destructor TbsNavDataLink.Destroy;
  49. begin
  50.   FNavigator := nil;
  51.   inherited Destroy;
  52. end;
  53. procedure TbsNavDataLink.EditingChanged;
  54. begin
  55.   if FNavigator <> nil then FNavigator.EditingChanged;
  56. end;
  57. procedure TbsNavDataLink.DataSetChanged;
  58. begin
  59.   if FNavigator <> nil then FNavigator.DataChanged;
  60. end;
  61. procedure TbsNavDataLink.ActiveChanged;
  62. begin
  63.   if FNavigator <> nil then FNavigator.ActiveChanged;
  64. end;
  65. constructor TbsSkinDBImage.Create(AOwner: TComponent);
  66. begin
  67.   inherited Create(AOwner);
  68.   Width := 105;
  69.   Height := 105;
  70.   TabStop := True;
  71.   FPicture := TPicture.Create;
  72.   FPicture.OnChange := PictureChanged;
  73.   FAutoDisplay := True;
  74.   FCenter := True;
  75.   FDataLink := TFieldDataLink.Create;
  76.   FDataLink.Control := Self;
  77.   FDataLink.OnDataChange := DataChange;
  78.   FDataLink.OnUpdateData := UpdateData;
  79.   FQuickDraw := True;
  80. end;
  81. destructor TbsSkinDBImage.Destroy;
  82. begin
  83.   FPicture.Free;
  84.   FDataLink.Free;
  85.   FDataLink := nil;
  86.   inherited Destroy;
  87. end;
  88. function TbsSkinDBImage.GetDataSource: TDataSource;
  89. begin
  90.   Result := FDataLink.DataSource;
  91. end;
  92. procedure TbsSkinDBImage.SetDataSource(Value: TDataSource);
  93. begin
  94.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  95.     FDataLink.DataSource := Value;
  96.   if Value <> nil then Value.FreeNotification(Self);
  97. end;
  98. function TbsSkinDBImage.GetDataField: string;
  99. begin
  100.   Result := FDataLink.FieldName;
  101. end;
  102. procedure TbsSkinDBImage.SetDataField(const Value: string);
  103. begin
  104.   FDataLink.FieldName := Value;
  105. end;
  106. function TbsSkinDBImage.GetReadOnly: Boolean;
  107. begin
  108.   Result := FDataLink.ReadOnly;
  109. end;
  110. procedure TbsSkinDBImage.SetReadOnly(Value: Boolean);
  111. begin
  112.   FDataLink.ReadOnly := Value;
  113. end;
  114. function TbsSkinDBImage.GetField: TField;
  115. begin
  116.   Result := FDataLink.Field;
  117. end;
  118. function TbsSkinDBImage.GetPalette: HPALETTE;
  119. begin
  120.   Result := 0;
  121.   if FPicture.Graphic is TBitmap then
  122.     Result := TBitmap(FPicture.Graphic).Palette;
  123. end;
  124. procedure TbsSkinDBImage.SetAutoDisplay(Value: Boolean);
  125. begin
  126.   if FAutoDisplay <> Value then
  127.   begin
  128.     FAutoDisplay := Value;
  129.     if Value then LoadPicture;
  130.   end;
  131. end;
  132. procedure TbsSkinDBImage.SetCenter(Value: Boolean);
  133. begin
  134.   if FCenter <> Value then
  135.   begin
  136.     FCenter := Value;
  137.     Invalidate;
  138.   end;
  139. end;
  140. procedure TbsSkinDBImage.SetPicture(Value: TPicture);
  141. begin
  142.   FPicture.Assign(Value);
  143. end;
  144. procedure TbsSkinDBImage.SetStretch(Value: Boolean);
  145. begin
  146.   if FStretch <> Value then
  147.   begin
  148.     FStretch := Value;
  149.     Invalidate;
  150.   end;
  151. end;
  152. procedure TbsSkinDBImage.CreateControlDefaultImage(B: TBitMap);
  153. begin
  154.   inherited;
  155.   if not RollUpState then PaintImage(B.Canvas);
  156. end;
  157. procedure TbsSkinDBImage.CreateControlSkinImage(B: TBitMap);
  158. begin
  159.   inherited;
  160.   if not RollUpState then PaintImage(B.Canvas);
  161. end;
  162. procedure TbsSkinDBImage.PaintImage;
  163. procedure DrawFocus(Cnvs: TCanvas; R: TRect);
  164. begin
  165.   with Cnvs do
  166.   begin
  167.     Pen.Color := clWindowFrame;
  168.     Pen.Mode := pmNot;
  169.     Brush.Style := bsClear;
  170.     Rectangle(R.Left, R.Top, R.Right, R.Bottom);
  171.   end;
  172. end;
  173. var
  174.   Size: TSize;
  175.   DrawRect, R: TRect;
  176.   S: string;
  177.   DrawPict: TPicture;
  178.   Form: TCustomForm;
  179.   Pal: HPalette;
  180. begin
  181.   DrawRect := Rect(0, 0, Width, Height);
  182.   AdjustClientRect(DrawRect);
  183.   with Cnvs do
  184.   begin
  185.     Brush.Style := bsClear;
  186.     if FPictureLoaded or (csPaintCopy in ControlState) then
  187.     begin
  188.       DrawPict := TPicture.Create;
  189.       Pal := 0;
  190.       try
  191.         if (csPaintCopy in ControlState) and
  192.           Assigned(FDataLink.Field) and FDataLink.Field.IsBlob
  193.         then
  194.           begin
  195.             DrawPict.Assign(FDataLink.Field);
  196.             if DrawPict.Graphic is TBitmap then
  197.               DrawPict.Bitmap.IgnorePalette := QuickDraw;
  198.           end
  199.         else
  200.           DrawPict.Assign(Picture);
  201.       if Stretch
  202.       then
  203.         begin
  204.          if (DrawPict.Graphic <> nil) and not DrawPict.Graphic.Empty
  205.          then
  206.             StretchDraw(DrawRect, DrawPict.Graphic);
  207.         end
  208.       else
  209.         begin
  210.           Windows.SetRect(R, DrawRect.Left, DrawRect.Top,
  211.                      DrawRect.Left + DrawPict.Width,
  212.                      DrawRect.Top + DrawPict.Height);
  213.           if Center
  214.           then
  215.             OffsetRect(R, ((DrawRect.Right - DrawRect.Left) - DrawPict.Width) div 2,
  216.             ((DrawRect.Bottom - DrawRect.Top) - DrawPict.Height) div 2);
  217.           StretchDraw(R, DrawPict.Graphic);
  218.         end;
  219.       finally
  220.         if Pal <> 0 then SelectPalette(Handle, Pal, True);
  221.         DrawPict.Free;
  222.       end;
  223.     end;
  224.     Form := GetParentForm(Self);
  225.     if (Form <> nil) and (Form.ActiveControl = Self) and
  226.       not (csDesigning in ComponentState) and
  227.       not (csPaintCopy in ControlState)
  228.     then
  229.       DrawFocus(Cnvs, DrawRect);
  230.   end;
  231. end;
  232. procedure TbsSkinDBImage.PictureChanged(Sender: TObject);
  233. begin
  234.   if FPictureLoaded then FDataLink.Modified;
  235.   FPictureLoaded := True;
  236.   Invalidate;
  237. end;
  238. procedure TbsSkinDBImage.Notification(AComponent: TComponent;
  239.   Operation: TOperation);
  240. begin
  241.   inherited Notification(AComponent, Operation);
  242.   if (Operation = opRemove) and (FDataLink <> nil) and
  243.     (AComponent = DataSource) then DataSource := nil;
  244. end;
  245. procedure TbsSkinDBImage.LoadPicture;
  246. begin
  247.   if not FPictureLoaded and (not Assigned(FDataLink.Field) or
  248.     FDataLink.Field.IsBlob) then
  249.     Picture.Assign(FDataLink.Field);
  250. end;
  251. procedure TbsSkinDBImage.DataChange(Sender: TObject);
  252. begin
  253.   Picture.Graphic := nil;
  254.   FPictureLoaded := False;
  255.   if FAutoDisplay then LoadPicture;
  256. end;
  257. procedure TbsSkinDBImage.UpdateData(Sender: TObject);
  258. begin
  259.   if Picture.Graphic is TBitmap then
  260.      FDataLink.Field.Assign(Picture.Graphic) else
  261.      FDataLink.Field.Clear;
  262. end;
  263. procedure TbsSkinDBImage.CopyToClipboard;
  264. begin
  265.   if Picture.Graphic <> nil then Clipboard.Assign(Picture);
  266. end;
  267. procedure TbsSkinDBImage.CutToClipboard;
  268. begin
  269.   if Picture.Graphic <> nil then
  270.     if FDataLink.Edit then
  271.     begin
  272.       CopyToClipboard;
  273.       Picture.Graphic := nil;
  274.     end;
  275. end;
  276. procedure TbsSkinDBImage.PasteFromClipboard;
  277. begin
  278.   if Clipboard.HasFormat(CF_BITMAP) and FDataLink.Edit then
  279.     Picture.Bitmap.Assign(Clipboard);
  280. end;
  281. procedure TbsSkinDBImage.CreateParams(var Params: TCreateParams);
  282. begin
  283.   inherited CreateParams(Params);
  284.   with Params do
  285.   begin
  286.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  287.   end;
  288. end;
  289. procedure TbsSkinDBImage.KeyDown(var Key: Word; Shift: TShiftState);
  290. begin
  291.   inherited KeyDown(Key, Shift);
  292.   case Key of
  293.     VK_INSERT:
  294.       if ssShift in Shift then PasteFromClipBoard else
  295.         if ssCtrl in Shift then CopyToClipBoard;
  296.     VK_DELETE:
  297.       if ssShift in Shift then CutToClipBoard;
  298.   end;
  299. end;
  300. procedure TbsSkinDBImage.KeyPress(var Key: Char);
  301. begin
  302.   inherited KeyPress(Key);
  303.   case Key of
  304.     ^X: CutToClipBoard;
  305.     ^C: CopyToClipBoard;
  306.     ^V: PasteFromClipBoard;
  307.     #13: LoadPicture;
  308.     #27: FDataLink.Reset;
  309.   end;
  310. end;
  311. procedure TbsSkinDBImage.CMGetDataLink(var Message: TMessage);
  312. begin
  313.   Message.Result := Integer(FDataLink);
  314. end;
  315. procedure TbsSkinDBImage.CMEnter(var Message: TCMEnter);
  316. begin
  317.   Invalidate; { Draw the focus marker }
  318.   inherited;
  319. end;
  320. procedure TbsSkinDBImage.CMExit(var Message: TCMExit);
  321. begin
  322.   try
  323.     FDataLink.UpdateRecord;
  324.   except
  325.     SetFocus;
  326.     raise;
  327.   end;
  328.   Invalidate; { Erase the focus marker }
  329.   inherited;
  330. end;
  331. procedure TbsSkinDBImage.CMTextChanged(var Message: TMessage);
  332. begin
  333.   inherited;
  334.   if not FPictureLoaded then Invalidate;
  335. end;
  336. procedure TbsSkinDBImage.WMLButtonDown(var Message: TWMLButtonDown);
  337. begin
  338.   if TabStop and CanFocus then SetFocus;
  339.   inherited;
  340. end;
  341. procedure TbsSkinDBImage.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  342. begin
  343.   LoadPicture;
  344.   inherited;
  345. end;
  346. procedure TbsSkinDBImage.WMCut(var Message: TMessage);
  347. begin
  348.   CutToClipboard;
  349. end;
  350. procedure TbsSkinDBImage.WMCopy(var Message: TMessage);
  351. begin
  352.   CopyToClipboard;
  353. end;
  354. procedure TbsSkinDBImage.WMPaste(var Message: TMessage);
  355. begin
  356.   PasteFromClipboard;
  357. end;
  358. procedure TbsSkinDBImage.WMSize(var Message: TMessage);
  359. begin
  360.   inherited;
  361.   Invalidate;
  362. end;
  363. function TbsSkinDBImage.ExecuteAction(Action: TBasicAction): Boolean;
  364. begin
  365.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  366.     FDataLink.ExecuteAction(Action);
  367. end;
  368. function TbsSkinDBImage.UpdateAction(Action: TBasicAction): Boolean;
  369. begin
  370.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  371.     FDataLink.UpdateAction(Action);
  372. end;
  373. { TbsSkinDBRadioGroup }
  374. constructor TbsSkinDBRadioGroup.Create(AOwner: TComponent);
  375. begin
  376.   inherited Create(AOwner);
  377.   FDataLink := TFieldDataLink.Create;
  378.   FDataLink.Control := Self;
  379.   FDataLink.OnDataChange := DataChange;
  380.   FDataLink.OnUpdateData := UpdateData;
  381.   FValues := TStringList.Create;
  382.   FInClick := False;
  383. end;
  384. destructor TbsSkinDBRadioGroup .Destroy;
  385. begin
  386.   FDataLink.Free;
  387.   FDataLink := nil;
  388.   FValues.Free;
  389.   inherited Destroy;
  390. end;
  391. procedure TbsSkinDBRadioGroup.Notification(AComponent: TComponent;
  392.   Operation: TOperation);
  393. begin
  394.   inherited Notification(AComponent, Operation);
  395.   if (Operation = opRemove) and (FDataLink <> nil) and
  396.     (AComponent = DataSource) then DataSource := nil;
  397. end;
  398. function TbsSkinDBRadioGroup .UseRightToLeftAlignment: Boolean;
  399. begin
  400.   Result := inherited UseRightToLeftAlignment;
  401. end;
  402. procedure TbsSkinDBRadioGroup.DataChange(Sender: TObject);
  403. begin
  404.   if not FInClick then
  405.   if FDataLink.Field <> nil then
  406.     Value := FDataLink.Field.Text else
  407.     Value := '';
  408. end;
  409. procedure TbsSkinDBRadioGroup.UpdateData(Sender: TObject);
  410. begin
  411.   if FDataLink.Field <> nil then FDataLink.Field.Text := Value;
  412. end;
  413. function TbsSkinDBRadioGroup.GetDataSource: TDataSource;
  414. begin
  415.   Result := FDataLink.DataSource;
  416. end;
  417. procedure TbsSkinDBRadioGroup.SetDataSource(Value: TDataSource);
  418. begin
  419.   FDataLink.DataSource := Value;
  420.   if Value <> nil then Value.FreeNotification(Self);
  421. end;
  422. function TbsSkinDBRadioGroup.GetDataField: string;
  423. begin
  424.   Result := FDataLink.FieldName;
  425. end;
  426. procedure TbsSkinDBRadioGroup.SetDataField(const Value: string);
  427. begin
  428.   FDataLink.FieldName := Value;
  429. end;
  430. function TbsSkinDBRadioGroup.GetReadOnly: Boolean;
  431. begin
  432.   Result := FDataLink.ReadOnly;
  433. end;
  434. procedure TbsSkinDBRadioGroup.SetReadOnly(Value: Boolean);
  435. begin
  436.   FDataLink.ReadOnly := Value;
  437. end;
  438. function TbsSkinDBRadioGroup.GetField: TField;
  439. begin
  440.   Result := FDataLink.Field;
  441. end;
  442. function TbsSkinDBRadioGroup.GetButtonValue(Index: Integer): string;
  443. begin
  444.   if (Index < FValues.Count) and (FValues[Index] <> '') then
  445.     Result := FValues[Index]
  446.   else if Index < Items.Count then
  447.     Result := Items[Index]
  448.   else
  449.     Result := '';
  450. end;
  451. procedure TbsSkinDBRadioGroup.SetValue(const Value: string);
  452. var
  453.   I, Index: Integer;
  454. begin
  455.   if FValue <> Value then
  456.   begin
  457.     FInSetValue := True;
  458.     try
  459.       Index := -1;
  460.       for I := 0 to Items.Count - 1 do
  461.         if Value = GetButtonValue(I) then
  462.         begin
  463.           Index := I;
  464.           Break;
  465.         end;
  466.       ItemIndex := Index;
  467.     finally
  468.       FInSetValue := False;
  469.     end;
  470.     FValue := Value;
  471.     Change;
  472.   end;
  473. end;
  474. procedure TbsSkinDBRadioGroup.CMExit(var Message: TCMExit);
  475. begin
  476.   try
  477.     FDataLink.UpdateRecord;
  478.   except
  479.     if ItemIndex >= 0 then
  480.       TRadioButton(Controls[ItemIndex]).SetFocus else
  481.       TRadioButton(Controls[0]).SetFocus;
  482.     raise;
  483.   end;
  484.   inherited;
  485. end;
  486. procedure TbsSkinDBRadioGroup.Click;
  487. begin
  488.   if not FInSetValue then
  489.   begin
  490.     inherited Click;
  491.     FInClick := True;
  492.     if ItemIndex >= 0
  493.     then Value := GetButtonValue(ItemIndex);
  494.     if not ReadOnly  and not FDataLink.Editing then FDataLink.Edit;
  495.     if FDataLink.Editing
  496.     then FDataLink.Modified;
  497.     FInClick := False;
  498.   end;
  499. end;
  500. procedure TbsSkinDBRadioGroup.SetItems(Value: TStrings);
  501. begin
  502.   Items.Assign(Value);
  503.   DataChange(Self);
  504. end;
  505. procedure TbsSkinDBRadioGroup.SetValues(Value: TStrings);
  506. begin
  507.   FValues.Assign(Value);
  508.   DataChange(Self);
  509. end;
  510. procedure TbsSkinDBRadioGroup.Change;
  511. begin
  512.   if Assigned(FOnChange) then FOnChange(Self);
  513. end;
  514. procedure TbsSkinDBRadioGroup.KeyPress(var Key: Char);
  515. begin
  516.   inherited KeyPress(Key);
  517.   case Key of
  518.     #8, ' ': FDataLink.Edit;
  519.     #27: FDataLink.Reset;
  520.   end;
  521. end;
  522. function TbsSkinDBRadioGroup.CanModify: Boolean;
  523. begin
  524.   Result := FDataLink.Edit;
  525. end;
  526. function TbsSkinDBRadioGroup.ExecuteAction(Action: TBasicAction): Boolean;
  527. begin
  528.   Result := inherited ExecuteAction(Action) or (DataLink <> nil) and
  529.     DataLink.ExecuteAction(Action);
  530. end;
  531. function TbsSkinDBRadioGroup.UpdateAction(Action: TBasicAction): Boolean;
  532. begin
  533.   Result := inherited UpdateAction(Action) or (DataLink <> nil) and
  534.     DataLink.UpdateAction(Action);
  535. end;
  536. constructor TbsSkinDBSpinEdit.Create(AOwner: TComponent);
  537. begin
  538.   inherited Create(AOwner);
  539.   ControlStyle := ControlStyle + [csReplicatable];
  540.   FDataLink := TFieldDataLink.Create;
  541.   FDataLink.Control := Self;
  542.   FDataLink.OnDataChange := DataChange;
  543.   FDataLink.OnEditingChange := EditingChange;
  544.   FDataLink.OnUpdateData := UpdateData;
  545.   FInChange := False;
  546.   FInDataChange := False;
  547. end;
  548. destructor TbsSkinDBSpinEdit.Destroy;
  549. begin
  550.   FDataLink.Free;
  551.   FDataLink := nil;
  552.   FCanvas.Free;
  553.   inherited Destroy;
  554. end;
  555. procedure TbsSkinDBSpinEdit.Loaded;
  556. begin
  557.   inherited Loaded;
  558.   if (csDesigning in ComponentState) then DataChange(Self);
  559. end;
  560. procedure TbsSkinDBSpinEdit.Notification(AComponent: TComponent;
  561.   Operation: TOperation);
  562. begin
  563.   inherited Notification(AComponent, Operation);
  564.   if (Operation = opRemove) and (FDataLink <> nil) and
  565.     (AComponent = DataSource) then DataSource := nil;
  566. end;
  567. procedure TbsSkinDBSpinEdit.Reset;
  568. begin
  569.   FDataLink.Reset;
  570.   FEdit.SelectAll;
  571. end;
  572. procedure TbsSkinDBSpinEdit.Change;
  573. begin
  574.   FInChange := True;
  575.   if not FInDataChange and (FDataLink <> nil) and
  576.      not ReadOnly and FDataLink.CanModify
  577.   then
  578.     begin
  579.       if not FDataLink.Editing then FDataLink.Edit; 
  580.       FDataLink.Modified;
  581.       inherited Change;
  582.     end;
  583.   FInChange := False;
  584. end;
  585. function TbsSkinDBSpinEdit.GetDataSource: TDataSource;
  586. begin
  587.   Result := FDataLink.DataSource;
  588. end;
  589. procedure TbsSkinDBSpinEdit.SetDataSource(Value: TDataSource);
  590. begin
  591.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  592.     FDataLink.DataSource := Value;
  593.   if Value <> nil then Value.FreeNotification(Self);
  594. end;
  595. function TbsSkinDBSpinEdit.GetDataField: string;
  596. begin
  597.   Result := FDataLink.FieldName;
  598. end;
  599. procedure TbsSkinDBSpinEdit.SetDataField(const Value: string);
  600. begin
  601.   FDataLink.FieldName := Value;
  602. end;
  603. function TbsSkinDBSpinEdit.GetReadOnly: Boolean;
  604. begin
  605.   Result := FDataLink.ReadOnly;
  606. end;
  607. procedure TbsSkinDBSpinEdit.SetReadOnly(Value: Boolean);
  608. begin
  609.   FDataLink.ReadOnly := Value;
  610. end;
  611. function TbsSkinDBSpinEdit.GetField: TField;
  612. begin
  613.   Result := FDataLink.Field;
  614. end;
  615. procedure TbsSkinDBSpinEdit.DataChange(Sender: TObject);
  616. begin
  617.   FInDataChange := True; 
  618.   if not FInChange then
  619.   if FDataLink.Field <> nil
  620.   then
  621.     begin
  622.       if (FDataLink.Field.Text <> '') and
  623.       IsNumText(FDataLink.Field.Text)
  624.       then Value := StrToInt(FDataLink.Field.Text)
  625.       else Value := MinValue;
  626.     end
  627.   else
  628.     Value := MinValue;
  629.   FInDataChange := False;
  630. end;
  631. procedure TbsSkinDBSpinEdit.EditingChange(Sender: TObject);
  632. begin
  633.   FEdit.ReadOnly := not FDataLink.Editing;
  634. end;
  635. procedure TbsSkinDBSpinEdit.UpdateData(Sender: TObject);
  636. begin
  637.   FDataLink.Field.Text := FEdit.Text;
  638. end;
  639. procedure TbsSkinDBSpinEdit.EditEnter;
  640. begin
  641.   inherited;
  642.   FEdit.ReadOnly := not FDataLink.CanModify;
  643. end;
  644. procedure TbsSkinDBSpinEdit.EditExit;
  645. begin
  646.   if (FDataLink <> nil) and (FDataLink.Editing)
  647.   then
  648.     FDataLink.UpdateRecord;
  649. end;
  650. procedure TbsSkinDBSpinEdit.CMGetDataLink(var Message: TMessage);
  651. begin
  652.   Message.Result := Integer(FDataLink);
  653. end;
  654. function TbsSkinDBSpinEdit.ExecuteAction(Action: TBasicAction): Boolean;
  655. begin
  656.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  657.     FDataLink.ExecuteAction(Action);
  658. end;
  659. function TbsSkinDBSpinEdit.UpdateAction(Action: TBasicAction): Boolean;
  660. begin
  661.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  662.     FDataLink.UpdateAction(Action);
  663. end;
  664. { TbsDataSourceLink }
  665. constructor TbsDataSourceLink.Create;
  666. begin
  667.   inherited Create;
  668.   VisualControl := True;
  669. end;
  670. procedure TbsDataSourceLink.ActiveChanged;
  671. begin
  672.   if FDBLookupControl <> nil then FDBLookupControl.UpdateDataFields;
  673. end;
  674. procedure TbsDataSourceLink.FocusControl(Field: TFieldRef);
  675. begin
  676.   if (Field^ <> nil) and (Field^ = FDBLookupControl.Field) and
  677.     (FDBLookupControl <> nil) and FDBLookupControl.CanFocus then
  678.   begin
  679.     Field^ := nil;
  680.     FDBLookupControl.SetFocus;
  681.   end;
  682. end;
  683. procedure TbsDataSourceLink.LayoutChanged;
  684. begin
  685.   if FDBLookupControl <> nil then FDBLookupControl.UpdateDataFields;
  686. end;
  687. procedure TbsDataSourceLink.RecordChanged(Field: TField);
  688. begin
  689.   if FDBLookupControl <> nil then FDBLookupControl.DataLinkRecordChanged(Field);
  690. end;
  691. { TbsListSourceLink }
  692. constructor TbsListSourceLink.Create;
  693. begin
  694.   inherited Create;
  695.   VisualControl := True;
  696. end;
  697. procedure TbsListSourceLink.ActiveChanged;
  698. begin
  699.   if FDBLookupControl <> nil then FDBLookupControl.UpdateListFields;
  700. end;
  701. procedure TbsListSourceLink.DataSetChanged;
  702. begin
  703.   if FDBLookupControl <> nil then FDBLookupControl.ListLinkDataChanged;
  704. end;
  705. procedure TbsListSourceLink.LayoutChanged;
  706. begin
  707.   if FDBLookupControl <> nil then FDBLookupControl.UpdateListFields;
  708. end;
  709. { TbsDBLookupControl }
  710. function VarEquals(const V1, V2: Variant): Boolean;
  711. begin
  712.   Result := False;
  713.   try
  714.     Result := V1 = V2;
  715.   except
  716.   end;
  717. end;
  718. var
  719.   SearchTickCount: Integer = 0;
  720. constructor TbsDBLookupControl.Create(AOwner: TComponent);
  721. begin
  722.   inherited Create(AOwner);
  723.   ParentColor := False;
  724.   TabStop := True;
  725.   FLookupSource := TDataSource.Create(Self);
  726.   FDataLink := TbsDataSourceLink.Create;
  727.   FDataLink.FDBLookupControl := Self;
  728.   FListLink := TbsListSourceLink.Create;
  729.   FListLink.FDBLookupControl := Self;
  730.   FListFields := TList.Create;
  731.   FKeyValue := Null;
  732. end;
  733. destructor TbsDBLookupControl.Destroy;
  734. begin
  735.   inherited Destroy;
  736.   FListFields.Free;
  737.   FListFields := nil;
  738.   if FListLink <> nil then
  739.     FListLink.FDBLookupControl := nil;
  740.   FListLink.Free;
  741.   FListLink := nil;
  742.   if FDataLink <> nil then
  743.     FDataLink.FDBLookupControl := nil;
  744.   FDataLink.Free;
  745.   FDataLink := nil;
  746. end;
  747. function TbsDBLookupControl.CanModify: Boolean;
  748. begin
  749.   Result := FListActive and not ReadOnly and ((FDataLink.DataSource = nil) or
  750.     (FMasterField <> nil) and FMasterField.CanModify);
  751. end;
  752. procedure TbsDBLookupControl.CheckNotCircular;
  753. begin
  754.   if FListLink.Active and FListLink.DataSet.IsLinkedTo(DataSource) then
  755.     DatabaseError('Circular datalinks are not allowed');
  756. end;
  757. procedure TbsDBLookupControl.CheckNotLookup;
  758. begin
  759.   if FLookupMode then DatabaseError('SPropDefByLookup');
  760.   if FDataLink.DataSourceFixed then DatabaseError('SDataSourceFixed');
  761. end;
  762. procedure TbsDBLookupControl.UpdateDataFields;
  763. begin
  764.   FDataField := nil;
  765.   FMasterField := nil;
  766.   if FDataLink.Active and (FDataFieldName <> '') then
  767.   begin
  768.     CheckNotCircular;
  769.     FDataField := GetFieldProperty(FDataLink.DataSet, Self, FDataFieldName);
  770.     if FDataField.FieldKind = fkLookup then
  771.       FMasterField := GetFieldProperty(FDataLink.DataSet, Self, FDataField.KeyFields)
  772.     else
  773.       FMasterField := FDataField;
  774.   end;
  775.   SetLookupMode((FDataField <> nil) and (FDataField.FieldKind = fkLookup));
  776.   DataLinkRecordChanged(nil);
  777. end;
  778. procedure TbsDBLookupControl.DataLinkRecordChanged(Field: TField);
  779. begin
  780.   if (Field = nil) or (Field = FMasterField) then
  781.     if FMasterField <> nil then
  782.       SetKeyValue(FMasterField.Value) else
  783.       SetKeyValue(Null);
  784. end;
  785. function TbsDBLookupControl.GetDataSource: TDataSource;
  786. begin
  787.   Result := FDataLink.DataSource;
  788. end;
  789. function TbsDBLookupControl.GetKeyFieldName: string;
  790. begin
  791.   if FLookupMode then Result := '' else Result := FKeyFieldName;
  792. end;
  793. function TbsDBLookupControl.GetListSource: TDataSource;
  794. begin
  795.   if FLookupMode then Result := nil else Result := FListLink.DataSource;
  796. end;
  797. function TbsDBLookupControl.GetReadOnly: Boolean;
  798. begin
  799.   Result := FDataLink.ReadOnly;
  800. end;
  801. procedure TbsDBLookupControl.KeyValueChanged;
  802. begin
  803. end;
  804. procedure TbsDBLookupControl.UpdateListFields;
  805. var
  806.   DataSet: TDataSet;
  807.   ResultField: TField;
  808. begin
  809.   FListActive := False;
  810.   FKeyField := nil;
  811.   FListField := nil;
  812.   FListFields.Clear;
  813.   if FListLink.Active and (FKeyFieldName <> '') then
  814.   begin
  815.     CheckNotCircular;
  816.     DataSet := FListLink.DataSet;
  817.     FKeyField := GetFieldProperty(DataSet, Self, FKeyFieldName);
  818.     try
  819.       DataSet.GetFieldList(FListFields, FListFieldName);
  820.     except
  821.       DatabaseErrorFmt('Field ''%s'' not found', [Self.Name, FListFieldName]);
  822.     end;
  823.     if FLookupMode then
  824.     begin
  825.       ResultField := GetFieldProperty(DataSet, Self, FDataField.LookupResultField);
  826.       if FListFields.IndexOf(ResultField) < 0 then
  827.         FListFields.Insert(0, ResultField);
  828.       FListField := ResultField;
  829.     end else
  830.     begin
  831.       if FListFields.Count = 0 then FListFields.Add(FKeyField);
  832.       if (FListFieldIndex >= 0) and (FListFieldIndex < FListFields.Count) then
  833.         FListField := FListFields[FListFieldIndex] else
  834.         FListField := FListFields[0];
  835.     end;
  836.     FListActive := True;
  837.   end;
  838. end;
  839. procedure TbsDBLookupControl.ListLinkDataChanged;
  840. begin
  841. end;
  842. function TbsDBLookupControl.LocateKey: Boolean;
  843. var
  844.   KeySave: Variant;
  845. begin
  846.   Result := False;
  847.   try
  848.     KeySave := FKeyValue;
  849.     if not VarIsNull(FKeyValue) and FListLink.DataSet.Active and
  850.       FListLink.DataSet.Locate(FKeyFieldName, FKeyValue, []) then
  851.     begin
  852.       Result := True;
  853.       FKeyValue := KeySave;
  854.     end;
  855.   except
  856.   end;
  857. end;
  858. procedure TbsDBLookupControl.Notification(AComponent: TComponent;
  859.   Operation: TOperation);
  860. begin
  861.   inherited Notification(AComponent, Operation);
  862.   if Operation = opRemove then
  863.   begin
  864.     if (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil;
  865.     if (FListLink <> nil) and (AComponent = ListSource) then ListSource := nil;
  866.   end;
  867. end;
  868. procedure TbsDBLookupControl.ProcessSearchKey(Key: Char);
  869. var
  870.   TickCount: Integer;
  871.   S: string;
  872.   CharMsg: TMsg;
  873. begin
  874.   if (FListField <> nil) and (FListField.FieldKind in [fkData, fkInternalCalc]) and
  875.     (FListField.DataType in [ftString, ftWideString]) then
  876.     case Key of
  877.       #8, #27: SearchText := '';
  878.       #32..#255:
  879.         if CanModify then
  880.         begin
  881.           TickCount := GetTickCount;
  882.           if TickCount - SearchTickCount > 2000 then SearchText := '';
  883.           SearchTickCount := TickCount;
  884.           if SysLocale.FarEast and (Key in LeadBytes) then
  885.             if PeekMessage(CharMsg, Handle, WM_CHAR, WM_CHAR, PM_REMOVE) then
  886.             begin
  887.               if CharMsg.Message = WM_Quit then
  888.               begin
  889.                 PostQuitMessage(CharMsg.wparam);
  890.                 Exit;
  891.               end;
  892.               SearchText := SearchText + Key;
  893.               Key := Char(CharMsg.wParam);
  894.             end;
  895.           if Length(SearchText) < 32 then
  896.           begin
  897.             S := SearchText + Key;
  898.             try
  899.               if FListLink.DataSet.Locate(FListField.FieldName, S,
  900.                 [loCaseInsensitive, loPartialKey]) then
  901.               begin
  902.                 SelectKeyValue(FKeyField.Value);
  903.                 SearchText := S;
  904.               end;
  905.             except
  906.               { If you attempt to search for a string larger than what the field
  907.                 can hold, and exception will be raised.  Just trap it and
  908.                 reset the SearchText back to the old value. }
  909.               SearchText := S;
  910.             end;
  911.           end;
  912.         end;
  913.     end;
  914. end;
  915. procedure TbsDBLookupControl.SelectKeyValue(const Value: Variant);
  916. begin
  917.   if FMasterField <> nil then
  918.   begin
  919.     if FDataLink.Edit then
  920.       FMasterField.Value := Value;
  921.   end else
  922.     SetKeyValue(Value);
  923.   Repaint;
  924.   Click;
  925. end;
  926. procedure TbsDBLookupControl.SetDataFieldName(const Value: string);
  927. begin
  928.   if FDataFieldName <> Value then
  929.   begin
  930.     FDataFieldName := Value;
  931.     UpdateDataFields;
  932.   end;
  933. end;
  934. procedure TbsDBLookupControl.SetDataSource(Value: TDataSource);
  935. begin
  936.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  937.     FDataLink.DataSource := Value;
  938.   if Value <> nil then Value.FreeNotification(Self);
  939. end;
  940. procedure TbsDBLookupControl.SetKeyFieldName(const Value: string);
  941. begin
  942.   CheckNotLookup;
  943.   if FKeyFieldName <> Value then
  944.   begin
  945.     FKeyFieldName := Value;
  946.     UpdateListFields;
  947.   end;
  948. end;
  949. procedure TbsDBLookupControl.SetKeyValue(const Value: Variant);
  950. begin
  951.   if not VarEquals(FKeyValue, Value) then
  952.   begin
  953.     FKeyValue := Value;
  954.     KeyValueChanged;
  955.   end;
  956. end;
  957. procedure TbsDBLookupControl.SetListFieldName(const Value: string);
  958. begin
  959.   if FListFieldName <> Value then
  960.   begin
  961.     FListFieldName := Value;
  962.     UpdateListFields;
  963.   end;
  964. end;
  965. procedure TbsDBLookupControl.SetListSource(Value: TDataSource);
  966. begin
  967.   CheckNotLookup;
  968.   FListLink.DataSource := Value;
  969.   if Value <> nil then Value.FreeNotification(Self);
  970. end;
  971. procedure TbsDBLookupControl.SetLookupMode(Value: Boolean);
  972. begin
  973.   if FLookupMode <> Value then
  974.     if Value then
  975.     begin
  976.       FMasterField := GetFieldProperty(FDataField.DataSet, Self, FDataField.KeyFields);
  977.       FLookupSource.DataSet := FDataField.LookupDataSet;
  978.       FKeyFieldName := FDataField.LookupKeyFields;
  979.       FLookupMode := True;
  980.       FListLink.DataSource := FLookupSource;
  981.     end else
  982.     begin
  983.       FListLink.DataSource := nil;
  984.       FLookupMode := False;
  985.       FKeyFieldName := '';
  986.       FLookupSource.DataSet := nil;
  987.       FMasterField := FDataField;
  988.     end;
  989. end;
  990. procedure TbsDBLookupControl.SetReadOnly(Value: Boolean);
  991. begin
  992.   FDataLink.ReadOnly := Value;
  993. end;
  994. procedure TbsDBLookupControl.WMGetDlgCode(var Message: TMessage);
  995. begin
  996.   Message.Result := DLGC_WANTARROWS or DLGC_WANTCHARS;
  997. end;
  998. procedure TbsDBLookupControl.WMKillFocus(var Message: TMessage);
  999. begin
  1000.   FHasFocus := False;
  1001.   inherited;
  1002.   Invalidate;
  1003. end;
  1004. procedure TbsDBLookupControl.WMSetFocus(var Message: TMessage);
  1005. begin
  1006.   SearchText := '';
  1007.   FHasFocus := True;
  1008.   inherited;
  1009.   Invalidate;
  1010. end;
  1011. procedure TbsDBLookupControl.CMEnabledChanged(var Message: TMessage);
  1012. begin
  1013.   inherited;
  1014.   Invalidate;
  1015. end;
  1016. procedure TbsDBLookupControl.CMGetDataLink(var Message: TMessage);
  1017. begin
  1018.   Message.Result := Integer(FDataLink);
  1019. end;
  1020. function TbsDBLookupControl.ExecuteAction(Action: TBasicAction): Boolean;
  1021. begin
  1022.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  1023.     FDataLink.ExecuteAction(Action);
  1024. end;
  1025. function TbsDBLookupControl.UpdateAction(Action: TBasicAction): Boolean;
  1026. begin
  1027.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  1028.     FDataLink.UpdateAction(Action);
  1029. end;
  1030. procedure TbsDBLookupControl.WMKeyDown(var Message: TWMKeyDown);
  1031. begin
  1032.   if (FNullValueKey <> 0) and CanModify and (FNullValueKey = ShortCut(Message.CharCode,
  1033.      KeyDataToShiftState(Message.KeyData))) then
  1034.   begin
  1035.     FDataLink.Edit;
  1036.     Field.Clear;
  1037.     Message.CharCode := 0;
  1038.   end;
  1039.   inherited;
  1040. end;
  1041. { TbsSkinDBLookupListBox }
  1042. constructor TbsSkinDBLookupListBox.Create(AOwner: TComponent);
  1043. begin
  1044.   inherited Create(AOwner);
  1045.   ControlStyle := ControlStyle + [csDoubleClicks];
  1046.   FSkinDataName := 'listbox';
  1047.   FDefaultItemHeight := 20;
  1048.   FScrollBar := nil;
  1049.   FStopThumbScroll := False;
  1050.   Width := 100;
  1051.   FRowCount := 7;
  1052. end;
  1053. destructor TbsSkinDBLookupListBox.Destroy;
  1054. begin
  1055.   inherited;
  1056. end;
  1057. procedure TbsSkinDBLookupListBox.ShowScrollBar;
  1058. begin
  1059.   if FScrollBar = nil
  1060.   then
  1061.     begin
  1062.       FScrollBar := TbsSkinScrollBar.Create(Self);
  1063.       FScrollBar.Kind := sbVertical;
  1064.       FScrollBar.Kind := sbVertical;
  1065.       if FIndex <> -1
  1066.       then
  1067.         FScrollBar.SkinDataName := ScrollBarName;
  1068.       FScrollBar.SkinData := SkinData;
  1069.       FScrollBar.Parent := Self;
  1070.       FScrollBar.DefaultWidth := 19;
  1071.       FScrollBar.OnChange := OnScrollBarChange;
  1072.       FScrollBar.OnUpButtonClick := OnScrollBarUpButtonClick;
  1073.       FScrollBar.OnDownButtonClick := OnScrollBarDownButtonClick;
  1074.       AlignScrollBar;
  1075.       RePaint;
  1076.     end;
  1077. end;
  1078. procedure TbsSkinDBLookupListBox.HideScrollBar;
  1079. begin
  1080.   if FScrollBar <> nil
  1081.   then
  1082.     begin
  1083.       FScrollBar.Visible := False;
  1084.       FScrollBar.Free;
  1085.       FScrollBar := nil;
  1086.       RePaint;
  1087.     end;
  1088. end;
  1089. type
  1090.   TXScrollBar = class(TBsSkinScrollBar);
  1091. procedure TbsSkinDBLookupListBox.OnScrollBarUpButtonClick;
  1092. begin
  1093.   FStopThumbScroll := True;
  1094.   SendMessage(Handle, WM_VSCROLL,
  1095.     MakeWParam(SB_LINEDOWN, FScrollBar.Position), 0);
  1096. end;
  1097. procedure TbsSkinDBLookupListBox.OnScrollBarDownButtonClick(Sender: TObject);
  1098. begin
  1099.   FStopThumbScroll := True;
  1100.   SendMessage(Handle, WM_VSCROLL,
  1101.     MakeWParam(SB_LINEUP, FScrollBar.Position), 0);
  1102. end;
  1103. procedure TbsSkinDBLookupListBox.OnScrollBarChange;
  1104. begin
  1105.   if not FStopThumbScroll then
  1106.   SendMessage(Handle, WM_VSCROLL,
  1107.               MakeWParam(SB_THUMBPOSITION, FScrollBar.Position), 0);
  1108.   FStopThumbScroll := False;            
  1109. end;
  1110. procedure TbsSkinDBLookupListBox.AlignScrollBar;
  1111. begin
  1112.   if FScrollBar <> nil
  1113.   then
  1114.     FScrollBar.SetBounds(ClientWidth - FScrollBar.Width, 0,
  1115.                          FScrollBar.Width, ClientHeight);
  1116. end;
  1117. procedure TbsSkinDBLookupListBox.ChangeSkinData;
  1118. begin
  1119.   inherited;
  1120.   if FScrollBar <> nil
  1121.   then
  1122.     begin
  1123.       if FIndex <> -1
  1124.       then
  1125.         begin
  1126.           FScrollBar.SkinDataName := ScrollBarName;
  1127.           FScrollBar.SkinData := SkinData;
  1128.         end
  1129.       else
  1130.         begin
  1131.           FScrollBar.SkinDataName := '';
  1132.           FScrollBar.ChangeSkinData;
  1133.         end;
  1134.     end;
  1135.   SetBounds(Left, Top, Width, Height);
  1136.   SendMessage(Handle, WM_NCPAINT, 0, 0);  
  1137. end;
  1138. function TbsSkinDBLookupListBox.GetItemHeight;
  1139. begin
  1140.   if FIndex = -1
  1141.   then
  1142.     Result := FDefaultItemHeight
  1143.   else
  1144.     Result := RectHeight(SItemRect);
  1145. end;
  1146. function TbsSkinDBLookupListBox.GetItemWidth;
  1147. begin
  1148.   Result := ClientWidth;
  1149.   if FScrollBar <> nil
  1150.   then
  1151.     Result := Result - FScrollBar.Width;
  1152. end;
  1153. function TbsSkinDBLookupListBox.GetBorderHeight;
  1154. begin
  1155.   if FIndex = -1
  1156.   then
  1157.     Result := 4
  1158.   else
  1159.     Result := RectHeight(SkinRect) - RectHeight(ClRect);
  1160. end;
  1161. procedure TbsSkinDBLookupListBox.GetSkinData;
  1162. begin
  1163.   inherited;
  1164.   if FIndex <> -1
  1165.   then
  1166.     if TbsDataSkinControl(FSD.CtrlList.Items[FIndex]) is TbsDataSkinListBox
  1167.     then
  1168.       with TbsDataSkinListBox(FSD.CtrlList.Items[FIndex]) do
  1169.       begin
  1170.         Self.FontName := FontName;
  1171.         Self.FontStyle := FontStyle;
  1172.         Self.FontHeight := FontHeight;
  1173.         Self.SItemRect := SItemRect;
  1174.         Self.ActiveItemRect := ActiveItemRect;
  1175.         if isNullRect(ActiveItemRect)
  1176.         then
  1177.           Self.ActiveItemRect := SItemRect;
  1178.         Self.FocusItemRect := FocusItemRect;
  1179.         if isNullRect(FocusItemRect)
  1180.         then
  1181.           Self.FocusItemRect := SItemRect;
  1182.         Self.ItemLeftOffset := ItemLeftOffset;
  1183.         Self.ItemRightOffset := ItemRightOffset;
  1184.         Self.ItemTextRect := ItemTextRect;
  1185.         Self.FontColor := FontColor;
  1186.         Self.ActiveFontColor := ActiveFontColor;
  1187.         Self.FocusFontColor := FocusFontColor;
  1188.         //
  1189.         Self.ScrollBarName := VScrollBarName;
  1190.       end;
  1191. end;
  1192. procedure TbsSkinDBLookupListBox.WMNCCALCSIZE;
  1193. begin
  1194.   GetSkinData;
  1195.   if FIndex = -1
  1196.   then
  1197.     with Message.CalcSize_Params^.rgrc[0] do
  1198.     begin
  1199.       Inc(Left, 2);
  1200.       Inc(Top, 2);
  1201.       Dec(Right, 2);
  1202.       Dec(Bottom, 2);
  1203.     end
  1204.   else
  1205.     with Message.CalcSize_Params^.rgrc[0] do
  1206.     begin
  1207.       Inc(Left, ClRect.Left);
  1208.       Inc(Top, ClRect.Top);
  1209.       Dec(Right, RectWidth(SkinRect) - ClRect.Right);
  1210.       Dec(Bottom, RectHeight(SkinRect) - ClRect.Bottom);
  1211.     end;
  1212. end;
  1213. procedure TbsSkinDBLookupListBox.FramePaint(C: TCanvas);
  1214. var
  1215.   R: TRect;
  1216.   LeftB, TopB, RightB, BottomB: TBitMap;
  1217.   OffX, OffY: Integer;
  1218. begin
  1219.   GetSkinData;
  1220.   if FIndex = -1
  1221.   then
  1222.     with C do
  1223.     begin
  1224.       Brush.Style := bsClear;
  1225.       Pen.Color := clBtnFace;
  1226.       Rectangle(1, 1, Width-1, Height-1);
  1227.       R := Rect(0, 0, Width, Height);
  1228.       Frame3D(C, R, clBtnShadow, clBtnShadow, 1);
  1229.       Exit;
  1230.     end;
  1231.   LeftB := TBitMap.Create;
  1232.   TopB := TBitMap.Create;
  1233.   RightB := TBitMap.Create;
  1234.   BottomB := TBitMap.Create;
  1235.   OffX := Width - RectWidth(SkinRect);
  1236.   OffY := Height - RectHeight(SkinRect);
  1237.   CreateSkinBorderImages(LTPt, RTPt, LBPt, RBPt, CLRect,
  1238.      NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
  1239.      LeftB, TopB, RightB, BottomB, Picture, SkinRect, Width, Height);
  1240.   C.Draw(0, 0, TopB);
  1241.   C.Draw(0, TopB.Height, LeftB);
  1242.   C.Draw(Width - RightB.Width, TopB.Height, RightB);
  1243.   C.Draw(0, Height - BottomB.Height, BottomB);
  1244.   TopB.Free;
  1245.   LeftB.Free;
  1246.   RightB.Free;
  1247.   BottomB.Free;
  1248. end;
  1249. procedure TbsSkinDBLookupListBox.WMNCPAINT;
  1250. var
  1251.   DC: HDC;
  1252.   C: TCanvas;
  1253. begin
  1254.   DC := GetWindowDC(Handle);
  1255.   C := TControlCanvas.Create;
  1256.   C.Handle := DC;
  1257.   try
  1258.     FramePaint(C);
  1259.   finally
  1260.     C.Free;
  1261.     ReleaseDC(Handle, DC);
  1262.   end;
  1263. end;
  1264. procedure TbsSkinDBLookupListBox.SetDefaultItemHeight;
  1265. begin
  1266.   if Value > 0
  1267.   then
  1268.     begin
  1269.       FDefaultItemHeight := Value;
  1270.       if FIndex = -1
  1271.       then
  1272.         SetBounds(Left, Top, Width, Height);
  1273.     end;  
  1274. end;
  1275. procedure TbsSkinDBLookupListBox.CreateParams(var Params: TCreateParams);
  1276. begin
  1277.   inherited CreateParams(Params);
  1278. end;
  1279. procedure TbsSkinDBLookupListBox.CreateWnd;
  1280. begin
  1281.   inherited CreateWnd;
  1282.   UpdateScrollBar;
  1283. end;
  1284. function TbsSkinDBLookupListBox.GetKeyIndex: Integer;
  1285. var
  1286.   FieldValue: Variant;
  1287. begin
  1288.   if not VarIsNull(FKeyValue) then
  1289.     for Result := 0 to FRecordCount - 1 do
  1290.     begin
  1291.       ListLink.ActiveRecord := Result;
  1292.       FieldValue := FKeyField.Value;
  1293.       ListLink.ActiveRecord := FRecordIndex;
  1294.       if VarEquals(FieldValue, FKeyValue) then Exit;
  1295.     end;
  1296.   Result := -1;
  1297. end;
  1298. procedure TbsSkinDBLookupListBox.KeyDown(var Key: Word; Shift: TShiftState);
  1299. var
  1300.   Delta, KeyIndex: Integer;
  1301. begin
  1302.   inherited KeyDown(Key, Shift);
  1303.   if CanModify then
  1304.   begin
  1305.     Delta := 0;
  1306.     case Key of
  1307.       VK_UP, VK_LEFT: Delta := -1;
  1308.       VK_DOWN, VK_RIGHT: Delta := 1;
  1309.       VK_PRIOR: Delta := 1 - FRowCount;
  1310.       VK_NEXT: Delta := FRowCount - 1;
  1311.       VK_HOME: Delta := -Maxint;
  1312.       VK_END: Delta := Maxint;
  1313.     end;
  1314.     if Delta <> 0 then
  1315.     begin
  1316.       SearchText := '';
  1317.       if Delta = -Maxint then ListLink.DataSet.First else
  1318.         if Delta = Maxint then ListLink.DataSet.Last else
  1319.         begin
  1320.           KeyIndex := GetKeyIndex;
  1321.           if KeyIndex >= 0 then
  1322.             ListLink.DataSet.MoveBy(KeyIndex - FRecordIndex)
  1323.           else
  1324.           begin
  1325.             KeyValueChanged;
  1326.             Delta := 0;
  1327.           end;
  1328.           ListLink.DataSet.MoveBy(Delta);
  1329.         end;
  1330.       SelectCurrent;
  1331.     end;
  1332.   end;
  1333. end;
  1334. procedure TbsSkinDBLookupListBox.KeyPress(var Key: Char);
  1335. begin
  1336.   inherited KeyPress(Key);
  1337.   ProcessSearchKey(Key);
  1338. end;
  1339. procedure TbsSkinDBLookupListBox.KeyValueChanged;
  1340. begin
  1341.   if ListActive and not FLockPosition then
  1342.     if not LocateKey then ListLink.DataSet.First;
  1343.   if FListField <> nil then
  1344.     FSelectedItem := FListField.DisplayText else
  1345.     FSelectedItem := '';
  1346. end;
  1347. procedure TbsSkinDBLookupListBox.UpdateListFields;
  1348. begin
  1349.   try
  1350.     inherited;
  1351.   finally
  1352.     if ListActive then KeyValueChanged else ListLinkDataChanged;
  1353.   end;
  1354. end;
  1355. procedure TbsSkinDBLookupListBox.ListLinkDataChanged;
  1356. begin
  1357.   if ListActive then
  1358.   begin
  1359.     FRecordIndex := ListLink.ActiveRecord;
  1360.     FRecordCount := ListLink.RecordCount;
  1361.     FKeySelected := not VarIsNull(FKeyValue) or
  1362.       not ListLink.DataSet.BOF;
  1363.   end else
  1364.   begin
  1365.     FRecordIndex := 0;
  1366.     FRecordCount := 0;
  1367.     FKeySelected := False;
  1368.   end;
  1369.   if HandleAllocated then
  1370.   begin
  1371.     UpdateScrollBar;
  1372.     Invalidate;
  1373.   end;
  1374. end;
  1375. procedure TbsSkinDBLookupListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
  1376.   X, Y: Integer);
  1377. begin
  1378.   if Button = mbLeft then
  1379.   begin
  1380.     SearchText := '';
  1381.     if not FPopup then
  1382.     begin
  1383.       SetFocus;
  1384.       if not HasFocus then Exit;
  1385.     end;
  1386.     if CanModify then
  1387.       if ssDouble in Shift then
  1388.       begin
  1389.         if FRecordIndex = Y div GetItemHeight then DblClick;
  1390.       end else
  1391.       begin
  1392.         MouseCapture := True;
  1393.         FTracking := True;
  1394.         SelectItemAt(X, Y);
  1395.       end;
  1396.   end;
  1397.   inherited MouseDown(Button, Shift, X, Y);
  1398. end;
  1399. procedure TbsSkinDBLookupListBox.MouseMove(Shift: TShiftState; X, Y: Integer);
  1400. begin
  1401.   if FTracking then
  1402.   begin
  1403.     SelectItemAt(X, Y);
  1404.     FMousePos := Y;
  1405.     TimerScroll;
  1406.   end;
  1407.   inherited MouseMove(Shift, X, Y);
  1408. end;
  1409. procedure TbsSkinDBLookupListBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1410.   X, Y: Integer);
  1411. begin
  1412.   if FTracking then
  1413.   begin
  1414.     StopTracking;
  1415.     SelectItemAt(X, Y);
  1416.   end;
  1417.   inherited MouseUp(Button, Shift, X, Y);
  1418. end;
  1419. procedure TbsSkinDBLookupListBox.CreateControlDefaultImage(B: TBitMap);
  1420. procedure DrawDefaultItem(R: TRect; ASelected, AFocused: Boolean;
  1421.                           S: String);
  1422. begin
  1423.   if ASelected
  1424.   then
  1425.     with B.Canvas do
  1426.     begin
  1427.       Brush.Style := bsSolid;
  1428.       Brush.Color := clHighLight;
  1429.       FillRect(R);
  1430.       Brush.Style := bsClear;
  1431.       Font.Color := clHighLightText;
  1432.     end
  1433.   else
  1434.     B.Canvas.Font.Color := DefaultFont.Color;
  1435.   //
  1436.   InflateRect(R, -2, -2);
  1437.   SPDrawText2(B.Canvas, S, R);
  1438.   InflateRect(R, 2, 2);
  1439.   //
  1440.   if AFocused
  1441.   then
  1442.     B.Canvas.DrawFocusRect(R);
  1443. end;
  1444. var
  1445.   I, J, LastFieldIndex: Integer;
  1446.   R: TRect;
  1447.   Selected: Boolean;
  1448.   Field: TField;
  1449.   S: String;
  1450.   W, TextWidth: Integer;
  1451. begin
  1452.   inherited;
  1453.   B.Width := GetItemWidth;
  1454.   with B.Canvas do
  1455.   begin
  1456.     Brush.Style := bsSolid;
  1457.     Brush.Color := clWindow;
  1458.     FillRect(ClientRect);
  1459.     Font := FDefaultFont;
  1460.     Brush.Style := bsClear;
  1461.   end;
  1462.   TextWidth := B.Canvas.TextWidth('0');
  1463.   R.Left := 0;
  1464.   R.Right := B.Width;
  1465.   LastFieldIndex := ListFields.Count - 1;
  1466.   for I := 0 to FRowCount - 1 do
  1467.   begin
  1468.     Selected := not FKeySelected and (I = 0);
  1469.     R.Top := I * GetItemHeight;
  1470.     R.Bottom := R.Top + GetItemHeight;
  1471.     if I < FRecordCount then
  1472.     begin
  1473.       ListLink.ActiveRecord := I;
  1474.       if not VarIsNull(FKeyValue) and
  1475.         VarEquals(FKeyField.Value, FKeyValue)
  1476.       then
  1477.         Selected := True;
  1478.       if LastFieldIndex = 0
  1479.       then
  1480.         begin
  1481.           Field := ListFields[0];
  1482.           DrawDefaultItem(R, Selected, Selected and (HasFocus or FPopup), Field.DisplayText);
  1483.         end
  1484.       else
  1485.         begin
  1486.           R.Left := 0;
  1487.           R.Right := 0;
  1488.           for J := 0 to LastFieldIndex do
  1489.           begin
  1490.             Field := ListFields[J];
  1491.             W := Field.DisplayWidth * TextWidth + 4;
  1492.             R.Right := R.Left + W;
  1493.             if R.Right > B.Width then R.Right := B.Width;
  1494.             if (J = LastFieldIndex) and (R.Right < B.Width)
  1495.             then R.Right := B.Width; 
  1496.             if RectWidth(R) > 0
  1497.             then
  1498.               DrawDefaultItem(R, Selected, Selected and (HasFocus or FPopup), Field.DisplayText);
  1499.             R.Left := R.Right;
  1500.           end;
  1501.         end;
  1502.     end;
  1503.   end;
  1504.   if FRecordCount <> 0 then ListLink.ActiveRecord := FRecordIndex;
  1505. end;
  1506. procedure TbsSkinDBLookupListBox.CreateControlSkinImage(B: TBitMap);
  1507. procedure DrawSkinItem(R: TRect; ASelected, AFocused: Boolean;
  1508.                        S: String);
  1509. var
  1510.   Buffer: TBitMap;
  1511.   TR: TRect;
  1512. begin
  1513.   if AFocused or ASelected
  1514.   then
  1515.     begin
  1516.       Buffer := TBitMap.Create;
  1517.       with Buffer.Canvas do
  1518.       begin
  1519.         Font.Name := FontName;
  1520.         Font.Height := FontHeight;
  1521.         Font.Style := FontStyle;
  1522.         if AFocused
  1523.         then Font.Color := FocusFontColor
  1524.         else Font.Color := ActiveFontColor;
  1525.         Brush.Style := bsClear;
  1526.       end;
  1527.       if AFocused
  1528.       then
  1529.         CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1530.         FocusItemRect, RectWidth(R), RectHeight(R))
  1531.       else
  1532.         CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1533.         ActiveItemRect, RectWidth(R), RectHeight(R));
  1534.       TR := ItemTextRect;
  1535.       Inc(TR.Right, Buffer.Width - RectWidth(SItemRect));
  1536.       SPDrawText2(Buffer.Canvas, S, TR);
  1537.       B.Canvas.Draw(R.Left, R.Top, Buffer);
  1538.       Buffer.Free;
  1539.     end
  1540.   else
  1541.     begin
  1542.       InflateRect(R, -2, -2);
  1543.       SPDrawText2(B.Canvas, S, R);
  1544.     end;
  1545. end;
  1546. procedure PaintBG;
  1547. var
  1548.   w, h, rw, rh, XCnt, YCnt, X, Y, XO, YO: Integer;
  1549. begin
  1550.   w := RectWidth(ClRect);
  1551.   h := RectHeight(ClRect);
  1552.   rw := B.Width;
  1553.   rh := B.Height;
  1554.   with B.Canvas do
  1555.   begin
  1556.     XCnt := rw div w;
  1557.     YCnt := rh div h;
  1558.     for X := 0 to XCnt do
  1559.     for Y := 0 to YCnt do
  1560.     begin
  1561.       if X * w + w > rw then XO := X * W + W - rw else XO := 0;
  1562.       if Y * h + h > rh then YO := Y * h + h - rh else YO := 0;
  1563.         CopyRect(Rect(X * w, Y * h,X * w + w - XO, Y * h + h - YO),
  1564.                  Picture.Canvas,
  1565.                  Rect(SkinRect.Left + ClRect.Left,
  1566.                  SkinRect.Top + ClRect.Top,
  1567.                  SkinRect.Left + ClRect.Right - XO,
  1568.                  SkinRect.Top + ClRect.Bottom - YO));
  1569.     end;
  1570.   end;
  1571. end;
  1572. var
  1573.   I, J, LastFieldIndex: Integer;
  1574.   R: TRect;
  1575.   Selected: Boolean;
  1576.   Field: TField;
  1577.   W, TextWidth: Integer;
  1578. begin
  1579.   B.Width := GetItemWidth;
  1580.   with B.Canvas do
  1581.   begin
  1582.     Font.Name := FontName;
  1583.     Font.Height := FontHeight;
  1584.     Font.Style := FontStyle;
  1585.     Font.Color := FontColor;
  1586.     Brush.Style := bsClear;
  1587.   end;
  1588.   TextWidth := B.Canvas.TextWidth('0');
  1589.   if not IsNullRect(ClRect) and (ClientWidth > 0) and (ClientHeight > 0)
  1590.   then
  1591.     PaintBG;
  1592.   R.Left := 0;
  1593.   R.Right := B.Width;
  1594.   LastFieldIndex := ListFields.Count - 1;
  1595.   for I := 0 to FRowCount - 1 do
  1596.   begin
  1597.     Selected := not FKeySelected and (I = 0);
  1598.     R.Top := I * GetItemHeight;
  1599.     R.Bottom := R.Top + GetItemHeight;
  1600.     if I < FRecordCount then
  1601.     begin
  1602.       ListLink.ActiveRecord := I;
  1603.       if not VarIsNull(FKeyValue) and
  1604.         VarEquals(FKeyField.Value, FKeyValue)
  1605.       then
  1606.         Selected := True;
  1607.       //
  1608.       if LastFieldIndex = 0
  1609.       then
  1610.         begin
  1611.           Field := ListFields[0];
  1612.           DrawSkinItem(R, Selected, Selected and (HasFocus or FPopup), Field.DisplayText);
  1613.         end
  1614.       else
  1615.         begin
  1616.           R.Left := 0;
  1617.           R.Right := 0;
  1618.           for J := 0 to LastFieldIndex do
  1619.           begin
  1620.             Field := ListFields[J];
  1621.             W := Field.DisplayWidth * TextWidth + RectWidth(SItemRect) -
  1622.                  RectWidth(ItemTextRect);
  1623.             R.Right := R.Left + W;
  1624.             if R.Right > B.Width then R.Right := B.Width;
  1625.             if (J = LastFieldIndex) and (R.Right < B.Width)
  1626.             then R.Right := B.Width;
  1627.             if RectWidth(R) > 0
  1628.             then
  1629.               DrawSkinItem(R, Selected, Selected and (HasFocus or FPopup), Field.DisplayText);
  1630.             R.Left := R.Right;
  1631.           end;
  1632.         end;
  1633.     end;
  1634.   end;
  1635.   if FRecordCount <> 0 then ListLink.ActiveRecord := FRecordIndex;
  1636. end;
  1637. procedure TbsSkinDBLookupListBox.SelectCurrent;
  1638. begin
  1639.   FLockPosition := True;
  1640.   try
  1641.     SelectKeyValue(FKeyField.Value);
  1642.   finally
  1643.     FLockPosition := False;
  1644.   end;
  1645. end;
  1646. procedure TbsSkinDBLookupListBox.SelectItemAt(X, Y: Integer);
  1647. var
  1648.   Delta: Integer;
  1649. begin
  1650.   if Y < 0 then Y := 0;
  1651.   if Y > ClientHeight then Y := ClientHeight;
  1652.   Delta := Y div GetItemHeight - FRecordIndex;
  1653.   ListLink.DataSet.MoveBy(Delta);
  1654.   SelectCurrent;
  1655. end;
  1656. procedure TbsSkinDBLookupListBox.SetBorderStyle(Value: TBorderStyle);
  1657. begin
  1658.   if FBorderStyle <> Value then
  1659.   begin
  1660.     FBorderStyle := Value;
  1661.     RecreateWnd;
  1662.     RowCount := RowCount;
  1663.   end;
  1664. end;
  1665. procedure TbsSkinDBLookupListBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  1666. var
  1667.   TextHeight, BorderHeight: Integer;
  1668. begin
  1669.   BorderHeight := GetBorderHeight;
  1670.   TextHeight := GetItemHeight;
  1671.   if Align = alNone
  1672.   then
  1673.     inherited SetBounds(ALeft, ATop, AWidth, FRowCount * TextHeight + BorderHeight)
  1674.   else
  1675.     begin
  1676.       FRowCount := (AHeight - BorderHeight) div TextHeight;
  1677.       inherited;
  1678.     end;
  1679.   if ListLink.BufferCount <> FRowCount then
  1680.   begin
  1681.     ListLink.BufferCount := FRowCount;
  1682.     ListLinkDataChanged;
  1683.   end;
  1684.   if HandleAllocated
  1685.   then
  1686.   SendMessage(Handle, WM_NCPAINT, 0, 0);
  1687.   AlignScrollBar;
  1688. end;
  1689. function TbsSkinDBLookupListBox.UseRightToLeftAlignment: Boolean;
  1690. begin
  1691.   Result := DBUseRightToLeftAlignment(Self, Field);
  1692. end;
  1693. procedure TbsSkinDBLookupListBox.SetRowCount(Value: Integer);
  1694. begin
  1695.   if Value < 1 then Value := 1;
  1696.   if Value > 100 then Value := 100;
  1697.   FRowCount := Value;
  1698.   Height := Value * GetItemHeight;
  1699. end;
  1700. procedure TbsSkinDBLookupListBox.StopTimer;
  1701. begin
  1702.   if FTimerActive then
  1703.   begin
  1704.     KillTimer(Handle, 1);
  1705.     FTimerActive := False;
  1706.   end;
  1707. end;
  1708. procedure TbsSkinDBLookupListBox.StopTracking;
  1709. begin
  1710.   if FTracking then
  1711.   begin
  1712.     StopTimer;
  1713.     FTracking := False;
  1714.     MouseCapture := False;
  1715.   end;
  1716. end;
  1717. procedure TbsSkinDBLookupListBox.TimerScroll;
  1718. var
  1719.   Delta, Distance, Interval: Integer;
  1720. begin
  1721.   Delta := 0;
  1722.   Distance := 0;
  1723.   if FMousePos < 0 then
  1724.   begin
  1725.     Delta := -1;
  1726.     Distance := -FMousePos;
  1727.   end;
  1728.   if FMousePos >= ClientHeight then
  1729.   begin
  1730.     Delta := 1;
  1731.     Distance := FMousePos - ClientHeight + 1;
  1732.   end;
  1733.   if Delta = 0 then StopTimer else
  1734.   begin
  1735.     if ListLink.DataSet.MoveBy(Delta) <> 0 then SelectCurrent;
  1736.     Interval := 200 - Distance * 15;
  1737.     if Interval < 0 then Interval := 0;
  1738.     SetTimer(Handle, 1, Interval, nil);
  1739.     FTimerActive := True;
  1740.   end;
  1741. end;
  1742. procedure TbsSkinDBLookupListBox.UpdateScrollBar;
  1743. var
  1744.   Pos, Max: Integer;
  1745.   ScrollInfo: TScrollInfo;
  1746. begin
  1747.   Pos := 0;
  1748.   Max := 0;
  1749.   if (FRowCount <> FRecordCount) or (KeyField = '') or
  1750.      (ListLink.DataSet = nil)
  1751.   then HideScrollBar
  1752.   else ShowScrollBar;
  1753.   if (FScrollBar <> nil)
  1754.   then
  1755.     begin
  1756.       if FRecordCount = FRowCount then
  1757.       begin
  1758.         Max := 4;
  1759.         if not ListLink.DataSet.BOF then
  1760.         if not ListLink.DataSet.EOF then Pos := 2 else Pos := 4;
  1761.       end;
  1762.       FScrollBar.SetRange(0, Max, Pos, 0);
  1763.     end;
  1764. end;
  1765. procedure TbsSkinDBLookupListBox.CMFontChanged(var Message: TMessage);
  1766. begin
  1767.   inherited;
  1768.   Height := Height;
  1769. end;
  1770. procedure TbsSkinDBLookupListBox.WMCancelMode(var Message: TMessage);
  1771. begin
  1772.   StopTracking;
  1773.   inherited;
  1774. end;
  1775. procedure TbsSkinDBLookupListBox.WMTimer(var Message: TMessage);
  1776. begin
  1777.   TimerScroll;
  1778. end;
  1779. procedure TbsSkinDBLookupListBox.WMVScroll(var Message: TWMVScroll);
  1780. begin
  1781.   SearchText := '';
  1782.   if ListLink.DataSet = nil then
  1783.     Exit;
  1784.   with Message, ListLink.DataSet do
  1785.     case ScrollCode of
  1786.       SB_LINEUP: MoveBy(-FRecordIndex - 1);
  1787.       SB_LINEDOWN: MoveBy(FRecordCount - FRecordIndex);
  1788.       SB_PAGEUP: MoveBy(-FRecordIndex - FRecordCount + 1);
  1789.       SB_PAGEDOWN: MoveBy(FRecordCount - FRecordIndex + FRecordCount - 2);
  1790.       SB_THUMBPOSITION:
  1791.         begin
  1792.           case Pos of
  1793.             0: First;
  1794.             1: MoveBy(-FRecordIndex - FRecordCount + 1);
  1795.             2: Exit;
  1796.             3: MoveBy(FRecordCount - FRecordIndex + FRecordCount - 2);
  1797.             4: Last;
  1798.           end;
  1799.         end;
  1800.       SB_BOTTOM: Last;
  1801.       SB_TOP: First;
  1802.     end;
  1803. end;
  1804. function TbsSkinDBLookupListBox.ExecuteAction(Action: TBasicAction): Boolean;
  1805. begin
  1806.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  1807.     FDataLink.ExecuteAction(Action);
  1808. end;
  1809. function TbsSkinDBLookupListBox.UpdateAction(Action: TBasicAction): Boolean;
  1810. begin
  1811.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  1812.     FDataLink.UpdateAction(Action);
  1813. end;
  1814. { TbsPopupDataList }
  1815. constructor TbsPopupDataList.Create(AOwner: TComponent);
  1816. begin
  1817.   inherited Create(AOwner);
  1818.   ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable];
  1819.   FPopup := True;
  1820. end;
  1821. procedure TbsPopupDataList.CreateParams(var Params: TCreateParams);
  1822. begin
  1823.   inherited CreateParams(Params);
  1824.   with Params do
  1825.   begin
  1826.     Style := WS_POPUP;
  1827.     ExStyle := WS_EX_TOOLWINDOW;
  1828.     AddBiDiModeExStyle(ExStyle);
  1829.     WindowClass.Style := CS_SAVEBITS;
  1830.   end;
  1831. end;
  1832. procedure TbsPopupDataList.WMMouseActivate(var Message: TMessage);
  1833. begin
  1834.   Message.Result := MA_NOACTIVATE;
  1835. end;
  1836. { TbsSkinDBLookupComboBox }
  1837. constructor TbsSkinDBLookupComboBox.Create(AOwner: TComponent);
  1838. begin
  1839.   inherited Create(AOwner);
  1840.   ControlStyle := ControlStyle + [csReplicatable];
  1841.   Width := 145;
  1842.   Height := 20;
  1843.   FDataList := TbsPopupDataList.Create(Self);
  1844.   FDataList.Visible := False;
  1845.   FDataList.TabStop := False;
  1846.   FDataList.Parent := Self;
  1847.   FDataList.OnMouseUp := ListMouseUp;
  1848.   FButtonWidth := 17;
  1849.   FDropDownRows := 7;
  1850.   FDefaultHeight := 20;
  1851.   FSkinDataName := 'combobox';
  1852. end;
  1853. procedure TbsSkinDBLookupComboBox.GetSkinData;
  1854. begin
  1855.   inherited;
  1856.   if FIndex <> -1
  1857.   then
  1858.     if TbsDataSkinControl(FSD.CtrlList.Items[FIndex]) is TbsDataSkinComboBox
  1859.     then
  1860.       with TbsDataSkinComboBox(FSD.CtrlList.Items[FIndex]) do
  1861.       begin
  1862.         Self.SItemRect := SItemRect;
  1863.         Self.FocusItemRect := FocusItemRect;
  1864.         if isNullRect(FocusItemRect)
  1865.         then
  1866.           Self.FocusItemRect := SItemRect;
  1867.         Self.ItemLeftOffset := ItemLeftOffset;
  1868.         Self.ItemRightOffset := ItemRightOffset;
  1869.         Self.ItemTextRect := ItemTextRect;
  1870.         Self.FontName := FontName;
  1871.         Self.FontStyle := FontStyle;
  1872.         Self.FontHeight := FontHeight;
  1873.         Self.FontColor := FontColor;
  1874.         Self.FocusFontColor := FocusFontColor;
  1875.         Self.ButtonRect := ButtonRect;
  1876.         Self.ActiveButtonRect := ActiveButtonRect;
  1877.         Self.DownButtonRect := DownButtonRect;
  1878.         Self.ListBoxName := ListBoxName;
  1879.       end;
  1880. end;
  1881. procedure TbsSkinDBLookupComboBox.CloseUp(Accept: Boolean);
  1882. var
  1883.   ListValue: Variant;
  1884. begin
  1885.   if FListVisible then
  1886.   begin
  1887.     if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  1888.     SetFocus;
  1889.     ListValue := FDataList.KeyValue;
  1890.     SetWindowPos(FDataList.Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
  1891.       SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
  1892.     FListVisible := False;
  1893.     FDataList.ListSource := nil;
  1894.     Invalidate;
  1895.     SearchText := '';
  1896.     if Accept and CanModify then SelectKeyValue(ListValue);
  1897.     if Assigned(FOnCloseUp) then FOnCloseUp(Self);
  1898.   end;
  1899. end;
  1900. procedure TbsSkinDBLookupComboBox.CMDialogKey(var Message: TCMDialogKey);
  1901. begin
  1902.   if (Message.CharCode in [VK_RETURN, VK_ESCAPE]) and FListVisible then
  1903.   begin
  1904.     CloseUp(Message.CharCode = VK_RETURN);
  1905.     Message.Result := 1;
  1906.   end else
  1907.     inherited;
  1908. end;
  1909. procedure TbsSkinDBLookupComboBox.CreateParams(var Params: TCreateParams);
  1910. begin
  1911.   inherited CreateParams(Params);
  1912. end;
  1913. procedure TbsSkinDBLookupComboBox.DropDown;
  1914. var
  1915.   P: TPoint;
  1916.   I, Y: Integer;
  1917.   S: string;
  1918.   ADropDownAlign: TDropDownAlign;
  1919. begin
  1920.   if not FListVisible and ListActive then
  1921.   begin
  1922.     if Assigned(FOnDropDown) then FOnDropDown(Self);
  1923.     if FDropDownWidth > 0 then
  1924.       FDataList.Width := FDropDownWidth else
  1925.       FDataList.Width := Width;
  1926.     FDataList.ReadOnly := not CanModify;
  1927.     if (ListLink.DataSet.RecordCount > 0) and
  1928.        (FDropDownRows > ListLink.DataSet.RecordCount) then
  1929.       FDataList.RowCount := ListLink.DataSet.RecordCount else
  1930.       FDataList.RowCount := FDropDownRows;
  1931.     FDataList.KeyField := FKeyFieldName;
  1932.     for I := 0 to ListFields.Count - 1 do
  1933.       S := S + TField(ListFields[I]).FieldName + ';';
  1934.     FDataList.ListField := S;
  1935.     FDataList.ListFieldIndex := ListFields.IndexOf(FListField);
  1936.     FDataList.ListSource := ListLink.DataSource;
  1937.     FDataList.KeyValue := KeyValue;
  1938.     P := Parent.ClientToScreen(Point(Left, Top));
  1939.     Y := P.Y + Height;
  1940.     if Y + FDataList.Height > Screen.Height then Y := P.Y - FDataList.Height;
  1941.     ADropDownAlign := FDropDownAlign;
  1942.     { This alignment is for the ListField, not the control }
  1943.     if DBUseRightToLeftAlignment(Self, FListField) then
  1944.     begin
  1945.       if ADropDownAlign = daLeft then
  1946.         ADropDownAlign := daRight
  1947.       else if ADropDownAlign = daRight then
  1948.         ADropDownAlign := daLeft;
  1949.     end;
  1950.     case ADropDownAlign of
  1951.       daRight: Dec(P.X, FDataList.Width - Width);
  1952.       daCenter: Dec(P.X, (FDataList.Width - Width) div 2);
  1953.     end;
  1954.     if FIndex = -1
  1955.     then
  1956.       begin
  1957.         FDataList.DefaultFont := DefaultFont;
  1958.         FDataList.DefaultItemHeight := Height - 2;
  1959.         FDataList.SkinDataName := ''
  1960.       end
  1961.     else
  1962.       FDataList.SkinDataName := ListBoxName;
  1963.     FDataList.SkinData := SkinData;
  1964.     SetWindowPos(FDataList.Handle, HWND_TOP, P.X, Y, 0, 0,
  1965.       SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW);
  1966.     FListVisible := True;
  1967.     FDataList.Visible := True;
  1968.     Repaint;
  1969.   end;
  1970. end;
  1971. procedure TbsSkinDBLookupComboBox.KeyDown(var Key: Word; Shift: TShiftState);
  1972. var
  1973.   Delta: Integer;
  1974. begin
  1975.   inherited KeyDown(Key, Shift);
  1976.   if ListActive and ((Key = VK_UP) or (Key = VK_DOWN)) then
  1977.     if ssAlt in Shift then
  1978.     begin
  1979.       if FListVisible then CloseUp(True) else DropDown;
  1980.       Key := 0;
  1981.     end else
  1982.       if not FListVisible then
  1983.       begin
  1984.         if not LocateKey then
  1985.           ListLink.DataSet.First
  1986.         else
  1987.         begin
  1988.           if Key = VK_UP then Delta := -1 else Delta := 1;
  1989.           ListLink.DataSet.MoveBy(Delta);
  1990.         end;
  1991.         SelectKeyValue(FKeyField.Value);
  1992.         Key := 0;
  1993.       end;
  1994.   if (Key <> 0) and FListVisible then FDataList.KeyDown(Key, Shift);
  1995. end;
  1996. procedure TbsSkinDBLookupComboBox.KeyPress(var Key: Char);
  1997. begin
  1998.   inherited KeyPress(Key);
  1999.   if FListVisible then
  2000.     if Key in [#13, #27] then
  2001.       CloseUp(Key = #13)
  2002.     else
  2003.       FDataList.KeyPress(Key)
  2004.   else
  2005.     ProcessSearchKey(Key);
  2006. end;
  2007. procedure TbsSkinDBLookupComboBox.KeyValueChanged;
  2008. begin
  2009.   if FLookupMode then
  2010.   begin
  2011.     FText := FDataField.DisplayText;
  2012.     FAlignment := FDataField.Alignment;
  2013.   end else
  2014.   if ListActive and LocateKey then
  2015.   begin
  2016.     FText := FListField.DisplayText;
  2017.     FAlignment := FListField.Alignment;
  2018.   end else
  2019.   begin
  2020.     FText := '';
  2021.     FAlignment := taLeftJustify;
  2022.   end;
  2023.   Invalidate;
  2024. end;
  2025. procedure TbsSkinDBLookupComboBox.UpdateListFields;
  2026. begin
  2027.   inherited;
  2028.   KeyValueChanged;
  2029. end;
  2030. procedure TbsSkinDBLookupComboBox.ListMouseUp(Sender: TObject; Button: TMouseButton;
  2031.   Shift: TShiftState; X, Y: Integer);
  2032. begin
  2033.   if Button = mbLeft then
  2034.     CloseUp(PtInRect(FDataList.ClientRect, Point(X, Y)));
  2035. end;
  2036. procedure TbsSkinDBLookupComboBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
  2037.   X, Y: Integer);
  2038. begin
  2039.   if Button = mbLeft then
  2040.   begin
  2041.     SetFocus;
  2042.     if not HasFocus then Exit;
  2043.     if FListVisible then CloseUp(False) else
  2044.       if ListActive then
  2045.       begin
  2046.         MouseCapture := True;
  2047.         FTracking := True;
  2048.         TrackButton(X, Y);
  2049.         DropDown;
  2050.       end;
  2051.   end;
  2052.   inherited MouseDown(Button, Shift, X, Y);
  2053. end;
  2054. procedure TbsSkinDBLookupComboBox.MouseMove(Shift: TShiftState; X, Y: Integer);
  2055. var
  2056.   ListPos: TPoint;
  2057.   MousePos: TSmallPoint;
  2058. begin
  2059.   if FTracking then
  2060.   begin
  2061.     TrackButton(X, Y);
  2062.     if FListVisible then
  2063.     begin
  2064.       ListPos := FDataList.ScreenToClient(ClientToScreen(Point(X, Y)));
  2065.       if PtInRect(FDataList.ClientRect, ListPos) then
  2066.       begin
  2067.         StopTracking;
  2068.         MousePos := PointToSmallPoint(ListPos);
  2069.         SendMessage(FDataList.Handle, WM_LBUTTONDOWN, 0, Integer(MousePos));
  2070.         Exit;
  2071.       end;
  2072.     end;
  2073.   end;
  2074.   inherited MouseMove(Shift, X, Y);
  2075. end;
  2076. procedure TbsSkinDBLookupComboBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
  2077.   X, Y: Integer);
  2078. begin
  2079.   StopTracking;
  2080.   inherited MouseUp(Button, Shift, X, Y);
  2081. end;
  2082. procedure TbsSkinDBLookupComboBox.CreateControlSkinImage;
  2083. var
  2084.   OX: Integer;
  2085.   Text: string;
  2086.   Selected: Boolean;
  2087.   R: TRect;
  2088.   TX, TY: Integer;
  2089.   Buffer: TBitMap;
  2090. begin
  2091.   inherited;
  2092.   with B.Canvas do
  2093.   begin
  2094.     Brush.Style := bsClear;
  2095.     Font.Name := FontName;
  2096.     Font.Style := FontStyle;
  2097.     Font.Height := FontHeight;
  2098.     Font.Color := FontColor;
  2099.   end;
  2100.   // calc rects
  2101.   OX := Width - RectWidth(SkinRect);
  2102.   FButtonRect := ButtonRect;
  2103.   if ButtonRect.Left >= RectWidth(SkinRect) - RTPt.X
  2104.   then
  2105.     OffsetRect(FButtonRect, OX, 0);
  2106.   FItemRect := ClRect;
  2107.   Inc(FItemRect.Right, OX);
  2108.   // draw button
  2109.   if FPressed and not IsNullRect(DownButtonRect)
  2110.   then
  2111.     B.Canvas.CopyRect(FButtonRect, Picture.Canvas, DownButtonRect);
  2112.   // draw item
  2113.   if (csPaintCopy in ControlState) and (FDataField <> nil) and
  2114.     (FDataField.Lookup)
  2115.   then
  2116.     Text := FDataField.DisplayText
  2117.   else
  2118.     begin
  2119.       if (csDesigning in ComponentState) and (FDataField = nil) then
  2120.       Text := Name else
  2121.       Text := FText;
  2122.     end;
  2123.   Selected := HasFocus and not FListVisible and
  2124.     not (csPaintCopy in ControlState);
  2125.   if Selected and not IsNullRect(FocusItemRect)
  2126.   then
  2127.     begin
  2128.       Buffer := TBitMap.Create;
  2129.       if not IsNullRect(FocusItemRect)
  2130.       then
  2131.         CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  2132.           FocusItemRect, RectWidth(FItemRect), RectHeight(FocusItemRect));
  2133.       B.Canvas.Draw(FItemRect.Left, FItemRect.Top, Buffer);
  2134.       Buffer.Free;
  2135.       R := ItemTextRect;
  2136.       Inc(R.Right, RectWidth(FItemRect) - RectWidth(FocusItemRect));
  2137.       OffsetRect(R, FItemRect.Left, FItemRect.Top);
  2138.       B.Canvas.Font.Color := FocusFontColor;
  2139.     end
  2140.   else
  2141.     R := FItemRect;
  2142.   TX := R.Left + 2;
  2143.   TY := R.Top + RectHeight(R) div 2 - B.Canvas.TextHeight(Text) div 2;
  2144.   B.Canvas.TextRect(R, TX, TY, Text);
  2145. end;
  2146. procedure TbsSkinDBLookupComboBox.CreateControlDefaultImage;
  2147. var
  2148.   W, X, Flags: Integer;
  2149.   Text: string;
  2150.   Selected: Boolean;
  2151.   R: TRect;
  2152.   TX, TY: Integer;
  2153. begin
  2154.   with B.Canvas do
  2155.   begin
  2156.     Brush.Color := clBtnFace;
  2157.     Brush.Style := bsSolid;
  2158.     R := ClientRect;
  2159.     FillRect(R);
  2160.     Font := DefaultFont;
  2161.   end;
  2162.   // frame
  2163.   Frame3D(B.Canvas, R, clbtnShadow, clbtnShadow, 1);
  2164.   // button
  2165.   R := Rect(Width - 2 - FButtonWidth, 2, Width - 2, Height - 2);
  2166.   if FPressed
  2167.   then
  2168.     begin
  2169.       Frame3D(B.Canvas, R, BS_XP_BTNFRAMECOLOR, BS_XP_BTNFRAMECOLOR,  1);
  2170.       B.Canvas.Brush.Color := BS_XP_BTNDOWNCOLOR;
  2171.       B.Canvas.FillRect(R);
  2172.     end
  2173.   else
  2174.     Frame3D(B.Canvas, R, clbtnShadow, clbtnShadow, 1);
  2175.   DrawArrowImage(B.Canvas, R, clBtnText, 4);
  2176.   // item
  2177.   if (csPaintCopy in ControlState) and (FDataField <> nil) and
  2178.     (FDataField.Lookup)
  2179.   then
  2180.     Text := FDataField.DisplayText
  2181.   else
  2182.     begin
  2183.       if (csDesigning in ComponentState) and (FDataField = nil) then
  2184.       Text := Name else
  2185.       Text := FText;
  2186.     end;
  2187.   Selected := HasFocus and not FListVisible and
  2188.     not (csPaintCopy in ControlState);
  2189.   if Enabled then
  2190.     B.Canvas.Font.Color := Font.Color
  2191.   else
  2192.     B.Canvas.Font.Color := clGrayText;
  2193.   if Selected
  2194.   then
  2195.     begin
  2196.      B.Canvas.Font.Color := clHighlightText;
  2197.      B.Canvas.Brush.Color := clHighlight;
  2198.     end
  2199.   else
  2200.     B.Canvas.Brush.Color := clWindow;
  2201.   TX := 4;
  2202.   TY := Height div 2 - B.Canvas.TextHeight(Text) div 2;
  2203.   R := Rect(2, 2, Width - 2 - FButtonWidth, Height - 2);
  2204.   B.Canvas.TextRect(R, TX, TY, Text);
  2205.   if Selected then B.Canvas.DrawFocusRect(R);
  2206. end;
  2207. procedure TbsSkinDBLookupComboBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  2208. begin
  2209.   inherited;
  2210. end;
  2211. function TbsSkinDBLookupComboBox.UseRightToLeftAlignment: Boolean;
  2212. begin
  2213.   Result := DBUseRightToLeftAlignment(Self, Field);
  2214. end;
  2215. procedure TbsSkinDBLookupComboBox.StopTracking;
  2216. begin
  2217.   if FTracking then
  2218.   begin
  2219.     TrackButton(-1, -1);
  2220.     FTracking := False;
  2221.     MouseCapture := False;
  2222.   end;
  2223. end;
  2224. procedure TbsSkinDBLookupComboBox.TrackButton(X, Y: Integer);
  2225. var
  2226.   NewState: Boolean;
  2227.   BR: TRect;
  2228. begin
  2229.   if FIndex = -1
  2230.   then
  2231.     NewState := PtInRect(Rect(ClientWidth - FButtonWidth - 2, 2, ClientWidth - 2,
  2232.                          ClientHeight - 2), Point(X, Y))
  2233.   else
  2234.     begin
  2235.       BR := FButtonRect;
  2236.       Inc(BR.Right);
  2237.       Inc(BR.Bottom);
  2238.       NewState := PtInRect(BR, Point(X, Y));
  2239.     end;
  2240.   if FPressed <> NewState then
  2241.   begin
  2242.     FPressed := NewState;
  2243.     Repaint;
  2244.   end;
  2245. end;
  2246. procedure TbsSkinDBLookupComboBox.CMCancelMode(var Message: TCMCancelMode);
  2247. begin
  2248.   if (Message.Sender <> Self) and (Message.Sender <> FDataList) and
  2249.      (Message.Sender <> FDataList.FScrollBar)
  2250.   then
  2251.     CloseUp(False);
  2252. end;
  2253. procedure TbsSkinDBLookupComboBox.CMFontChanged(var Message: TMessage);
  2254. begin
  2255.   inherited;
  2256. end;
  2257. procedure TbsSkinDBLookupComboBox.CMGetDataLink(var Message: TMessage);
  2258. begin
  2259.   Message.Result := Integer(FDataLink);
  2260. end;
  2261. procedure TbsSkinDBLookupComboBox.WMCancelMode(var Message: TMessage);
  2262. begin
  2263.   StopTracking;
  2264.   inherited;
  2265. end;
  2266. procedure TbsSkinDBLookupComboBox.WMKillFocus(var Message: TWMKillFocus);
  2267. begin
  2268.   inherited;
  2269.   CloseUp(False);
  2270. end;
  2271. function TbsSkinDBLookupComboBox.ExecuteAction(Action: TBasicAction): Boolean;
  2272. begin
  2273.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  2274.     FDataLink.ExecuteAction(Action);
  2275. end;
  2276. function TbsSkinDBLookupComboBox.UpdateAction(Action: TBasicAction): Boolean;
  2277. begin
  2278.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  2279.     FDataLink.UpdateAction(Action);
  2280. end;
  2281. { TbsSkinDBRichEdit }
  2282. constructor TbsSkinDBRichEdit.Create(AOwner: TComponent);
  2283. begin
  2284.   inherited Create(AOwner);
  2285.   inherited ReadOnly := True;
  2286.   FAutoDisplay := True;
  2287.   FDataLink := TFieldDataLink.Create;
  2288.   FDataLink.Control := Self;
  2289.   FDataLink.OnDataChange := DataChange;
  2290.   FDataLink.OnEditingChange := EditingChange;
  2291.   FDataLink.OnUpdateData := UpdateData;
  2292. end;
  2293. destructor TbsSkinDBRichEdit.Destroy;
  2294. begin
  2295.   FDataLink.Free;
  2296.   FDataLink := nil;
  2297.   inherited Destroy;
  2298. end;
  2299. procedure TbsSkinDBRichEdit.Loaded;
  2300. begin
  2301.   inherited Loaded;
  2302.   if (csDesigning in ComponentState) then DataChange(Self);
  2303. end;
  2304. procedure TbsSkinDBRichEdit.Notification(AComponent: TComponent;
  2305.   Operation: TOperation);
  2306. begin
  2307.   inherited Notification(AComponent, Operation);
  2308.   if (Operation = opRemove) and (FDataLink <> nil) and
  2309.     (AComponent = DataSource) then DataSource := nil;
  2310. end;
  2311. function TbsSkinDBRichEdit.UseRightToLeftAlignment: Boolean;
  2312. begin
  2313.   Result := DBUseRightToLeftAlignment(Self, Field);
  2314. end;
  2315. procedure TbsSkinDBRichEdit.BeginEditing;
  2316. begin
  2317.   if not FDataLink.Editing then
  2318.   try
  2319.     if FDataLink.Field.IsBlob then
  2320.       FDataSave := FDataLink.Field.AsString;
  2321.     FDataLink.Edit;
  2322.   finally
  2323.     FDataSave := '';
  2324.   end;
  2325. end;
  2326. procedure TbsSkinDBRichEdit.KeyDown(var Key: Word; Shift: TShiftState);
  2327. begin
  2328.   inherited KeyDown(Key, Shift);
  2329.   if FMemoLoaded then
  2330.   begin
  2331.     if (Key = VK_DELETE) or (Key = VK_BACK) or
  2332.       ((Key = VK_INSERT) and (ssShift in Shift)) or
  2333.       (((Key = Ord('V')) or (Key = Ord('X'))) and (ssCtrl in Shift)) then
  2334.       BeginEditing;
  2335.   end;
  2336. end;
  2337. procedure TbsSkinDBRichEdit.KeyPress(var Key: Char);
  2338. begin
  2339.   inherited KeyPress(Key);
  2340.   if FMemoLoaded then
  2341.   begin
  2342.     if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
  2343.       not FDataLink.Field.IsValidChar(Key) then
  2344.     begin
  2345.       MessageBeep(0);
  2346.       Key := #0;
  2347.     end;
  2348.     case Key of
  2349.       ^H, ^I, ^J, ^M, ^V, ^X, #32..#255:
  2350.         BeginEditing;
  2351.       #27:
  2352.         FDataLink.Reset;
  2353.     end;
  2354.   end else
  2355.   begin
  2356.     if Key = #13 then LoadMemo;
  2357.     Key := #0;
  2358.   end;
  2359. end;
  2360. procedure TbsSkinDBRichEdit.Change;
  2361. begin
  2362.   if FMemoLoaded then FDataLink.Modified;
  2363.   FMemoLoaded := True;
  2364.   inherited Change;
  2365. end;
  2366. function TbsSkinDBRichEdit.GetDataSource: TDataSource;
  2367. begin
  2368.   Result := FDataLink.DataSource;
  2369. end;
  2370. procedure TbsSkinDBRichEdit.SetDataSource(Value: TDataSource);
  2371. begin
  2372.   FDataLink.DataSource := Value;
  2373.   if Value <> nil then Value.FreeNotification(Self);
  2374. end;
  2375. function TbsSkinDBRichEdit.GetDataField: string;
  2376. begin
  2377.   Result := FDataLink.FieldName;
  2378. end;
  2379. procedure TbsSkinDBRichEdit.SetDataField(const Value: string);
  2380. begin
  2381.   FDataLink.FieldName := Value;
  2382. end;
  2383. function TbsSkinDBRichEdit.GetReadOnly: Boolean;
  2384. begin
  2385.   Result := FDataLink.ReadOnly;
  2386. end;
  2387. procedure TbsSkinDBRichEdit.SetReadOnly(Value: Boolean);
  2388. begin
  2389.   FDataLink.ReadOnly := Value;
  2390. end;
  2391. function TbsSkinDBRichEdit.GetField: TField;
  2392. begin
  2393.   Result := FDataLink.Field;
  2394. end;
  2395. procedure TbsSkinDBRichEdit.LoadMemo;
  2396. begin
  2397.   if not FMemoLoaded and Assigned(FDataLink.Field) and FDataLink.Field.IsBlob then
  2398.   begin
  2399.     try
  2400.       Lines.Assign(FDataLink.Field);
  2401.       FMemoLoaded := True;
  2402.     except
  2403.       { Rich Edit Load failure }
  2404.       on E:EOutOfResources do
  2405.         Lines.Text := Format('(%s)', [E.Message]);
  2406.     end;
  2407.     EditingChange(Self);
  2408.   end;
  2409. end;
  2410. procedure TbsSkinDBRichEdit.DataChange(Sender: TObject);
  2411. begin
  2412.   if FDataLink.Field <> nil then
  2413.     if FDataLink.Field.IsBlob then
  2414.     begin
  2415.       if FAutoDisplay or (FDataLink.Editing and FMemoLoaded) then
  2416.       begin
  2417.         { Check if the data has changed since we read it the first time }
  2418.         if (FDataSave <> '') and (FDataSave = FDataLink.Field.AsString) then Exit;
  2419.         FMemoLoaded := False;
  2420.         LoadMemo;
  2421.       end else
  2422.       begin
  2423.         Text := Format('(%s)', [FDataLink.Field.DisplayLabel]);
  2424.         FMemoLoaded := False;
  2425.       end;
  2426.     end else
  2427.     begin
  2428.       if FFocused and FDataLink.CanModify then
  2429.         Text := FDataLink.Field.Text
  2430.       else
  2431.         Text := FDataLink.Field.DisplayText;
  2432.       FMemoLoaded := True;
  2433.     end
  2434.   else
  2435.   begin
  2436.     if csDesigning in ComponentState then Text := Name else Text := '';
  2437.     FMemoLoaded := False;
  2438.   end;
  2439.   if HandleAllocated then
  2440.     RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ERASE or RDW_FRAME);
  2441. end;
  2442. procedure TbsSkinDBRichEdit.EditingChange(Sender: TObject);
  2443. begin
  2444.   inherited ReadOnly := not (FDataLink.Editing and FMemoLoaded);
  2445. end;
  2446. procedure TbsSkinDBRichEdit.UpdateData(Sender: TObject);
  2447. begin
  2448.   if FDataLink.Field.IsBlob then
  2449.     FDataLink.Field.Assign(Lines) else
  2450.     FDataLink.Field.AsString := Text;
  2451. end;
  2452. procedure TbsSkinDBRichEdit.SetFocused(Value: Boolean);
  2453. begin
  2454.   if FFocused <> Value then
  2455.   begin
  2456.     FFocused := Value;
  2457.     if not Assigned(FDataLink.Field) or not FDataLink.Field.IsBlob then
  2458.       FDataLink.Reset;
  2459.   end;
  2460. end;
  2461. procedure TbsSkinDBRichEdit.CMEnter(var Message: TCMEnter);
  2462. begin
  2463.   SetFocused(True);
  2464.   inherited;
  2465.   if SysLocale.FarEast and FDataLink.CanModify then
  2466.     inherited ReadOnly := False;
  2467. end;
  2468. procedure TbsSkinDBRichEdit.CMExit(var Message: TCMExit);
  2469. begin
  2470.   try
  2471.     FDataLink.UpdateRecord;
  2472.   except
  2473.     SetFocus;
  2474.     raise;
  2475.   end;
  2476.   SetFocused(False);
  2477.   inherited;
  2478. end;
  2479. procedure TbsSkinDBRichEdit.SetAutoDisplay(Value: Boolean);
  2480. begin
  2481.   if FAutoDisplay <> Value then
  2482.   begin
  2483.     FAutoDisplay := Value;
  2484.     if Value then LoadMemo;
  2485.   end;
  2486. end;
  2487. procedure TbsSkinDBRichEdit.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  2488. begin
  2489.   if not FMemoLoaded then LoadMemo else inherited;
  2490. end;
  2491. procedure TbsSkinDBRichEdit.WMCut(var Message: TMessage);
  2492. begin
  2493.   BeginEditing;
  2494.   inherited;
  2495. end;
  2496. procedure TbsSkinDBRichEdit.WMPaste(var Message: TMessage);
  2497. begin
  2498.   BeginEditing;
  2499.   inherited;
  2500. end;
  2501. procedure TbsSkinDBRichEdit.CMGetDataLink(var Message: TMessage);
  2502. begin
  2503.   Message.Result := Integer(FDataLink);
  2504. end;
  2505. function TbsSkinDBRichEdit.ExecuteAction(Action: TBasicAction): Boolean;
  2506. begin
  2507.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  2508.     FDataLink.ExecuteAction(Action);
  2509. end;
  2510. function TbsSkinDBRichEdit.UpdateAction(Action: TBasicAction): Boolean;
  2511. begin
  2512.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  2513.     FDataLink.UpdateAction(Action);
  2514. end;
  2515. constructor TbsSkinDBCalcEdit.Create(AOwner: TComponent);
  2516. begin
  2517.   inherited Create(AOwner);
  2518.   ControlStyle := ControlStyle + [csReplicatable];
  2519.   FDataLink := TFieldDataLink.Create;
  2520.   FDataLink.Control := Self;
  2521.   FDataLink.OnDataChange := DataChange;
  2522.   FDataLink.OnEditingChange := EditingChange;
  2523.   FDataLink.OnUpdateData := UpdateData;
  2524.   FInChange := False;
  2525.   FInDataChange := False;
  2526. end;
  2527. destructor TbsSkinDBCalcEdit.Destroy;
  2528. begin
  2529.   FDataLink.Free;
  2530.   FDataLink := nil;
  2531.   inherited Destroy;
  2532. end;
  2533. procedure TbsSkinDBCalcEdit.Loaded;
  2534. begin
  2535.   inherited Loaded;
  2536.   if (csDesigning in ComponentState) then DataChange(Self);
  2537. end;
  2538. procedure TbsSkinDBCalcEdit.Notification(AComponent: TComponent;
  2539.   Operation: TOperation);
  2540. begin
  2541.   inherited Notification(AComponent, Operation);
  2542.   if (Operation = opRemove) and (FDataLink <> nil) and
  2543.     (AComponent = DataSource) then DataSource := nil;
  2544. end;
  2545. procedure TbsSkinDBCalcEdit.Reset;
  2546. begin
  2547.   FDataLink.Reset;
  2548.   SelectAll;
  2549. end;
  2550. procedure TbsSkinDBCalcEdit.Change;
  2551. begin
  2552.   FInChange := True;
  2553.   if not FInDataChange and (FDataLink <> nil) and
  2554.      not ReadOnly and FDataLink.CanModify
  2555.   then
  2556.     begin
  2557.       if not FDataLink.Editing then FDataLink.Edit; 
  2558.       FDataLink.Modified;
  2559.       inherited Change;
  2560.     end;
  2561.   FInChange := False;
  2562. end;
  2563. function TbsSkinDBCalcEdit.GetDataSource: TDataSource;
  2564. begin
  2565.   Result := FDataLink.DataSource;
  2566. end;
  2567. procedure TbsSkinDBCalcEdit.SetDataSource(Value: TDataSource);
  2568. begin
  2569.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  2570.     FDataLink.DataSource := Value;
  2571.   if Value <> nil then Value.FreeNotification(Self);
  2572. end;
  2573. function TbsSkinDBCalcEdit.GetDataField: string;
  2574. begin
  2575.   Result := FDataLink.FieldName;
  2576. end;
  2577. procedure TbsSkinDBCalcEdit.SetDataField(const Value: string);
  2578. begin
  2579.   FDataLink.FieldName := Value;
  2580. end;
  2581. function TbsSkinDBCalcEdit.GetReadOnly: Boolean;
  2582. begin
  2583.   Result := FDataLink.ReadOnly;
  2584. end;
  2585. procedure TbsSkinDBCalcEdit.SetReadOnly(Value: Boolean);
  2586. begin
  2587.   FDataLink.ReadOnly := Value;
  2588. end;
  2589. function TbsSkinDBCalcEdit.GetField: TField;
  2590. begin
  2591.   Result := FDataLink.Field;
  2592. end;
  2593. procedure TbsSkinDBCalcEdit.DataChange(Sender: TObject);
  2594. begin
  2595.   FInDataChange := True; 
  2596.   if not FInChange then
  2597.   if FDataLink.Field <> nil
  2598.   then
  2599.     begin
  2600.       if (FDataLink.Field.Text <> '') and
  2601.       IsNumText(FDataLink.Field.Text)
  2602.       then Value := StrToInt(FDataLink.Field.Text)
  2603.       else Value := MinValue;
  2604.     end
  2605.   else
  2606.     Value := MinValue;
  2607.   FInDataChange := False;
  2608. end;
  2609. procedure TbsSkinDBCalcEdit.EditingChange(Sender: TObject);
  2610. begin
  2611.   inherited ReadOnly := not FDataLink.Editing;
  2612. end;
  2613. procedure TbsSkinDBCalcEdit.UpdateData(Sender: TObject);
  2614. begin
  2615.   FDataLink.Field.Text := Text;
  2616. end;
  2617. procedure TbsSkinDBCalcEdit.CMEnter;
  2618. begin
  2619.   inherited;
  2620.   inherited ReadOnly := not FDataLink.CanModify;
  2621. end;
  2622. procedure TbsSkinDBCalcEdit.CMExit;
  2623. begin
  2624.   inherited;
  2625.   if (FDataLink <> nil) and (FDataLink.Editing)
  2626.   then
  2627.     FDataLink.UpdateRecord;
  2628. end;
  2629. procedure TbsSkinDBCalcEdit.CMGetDataLink(var Message: TMessage);
  2630. begin
  2631.   Message.Result := Integer(FDataLink);
  2632. end;
  2633. function TbsSkinDBCalcEdit.ExecuteAction(Action: TBasicAction): Boolean;
  2634. begin
  2635.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  2636.     FDataLink.ExecuteAction(Action);
  2637. end;
  2638. function TbsSkinDBCalcEdit.UpdateAction(Action: TBasicAction): Boolean;
  2639. begin
  2640.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  2641.     FDataLink.UpdateAction(Action);
  2642. end;
  2643. constructor TbsSkinDBMemo2.Create(AOwner: TComponent);
  2644. begin
  2645.   inherited Create(AOwner);
  2646.   inherited ReadOnly := True;
  2647.   ControlStyle := ControlStyle + [csReplicatable];
  2648.   FAutoDisplay := True;
  2649.   FDataLink := TFieldDataLink.Create;
  2650.   FDataLink.Control := Self;
  2651.   FDataLink.OnDataChange := DataChange;
  2652.   FDataLink.OnEditingChange := EditingChange;
  2653.   FDataLink.OnUpdateData := UpdateData;
  2654. end;
  2655. destructor TbsSkinDBMemo2.Destroy;
  2656. begin
  2657.   FDataLink.Free;
  2658.   FDataLink := nil;
  2659.   inherited Destroy;
  2660. end;
  2661. procedure TbsSkinDBMemo2.Loaded;
  2662. begin
  2663.   inherited Loaded;
  2664. //  if (csDesigning in ComponentState) then DataChange(Self);
  2665. end;
  2666. procedure TbsSkinDBMemo2.Notification(AComponent: TComponent;
  2667.   Operation: TOperation);
  2668. begin
  2669.   inherited Notification(AComponent, Operation);
  2670.   if (Operation = opRemove) and (FDataLink <> nil) and
  2671.     (AComponent = DataSource) then DataSource := nil;
  2672. end;
  2673. function TbsSkinDBMemo2.UseRightToLeftAlignment: Boolean;
  2674. begin
  2675.   Result := DBUseRightToLeftAlignment(Self, Field);
  2676. end;
  2677. procedure TbsSkinDBMemo2.KeyDown(var Key: Word; Shift: TShiftState);
  2678. begin
  2679.   inherited KeyDown(Key, Shift);
  2680.   if FMemoLoaded then
  2681.   begin
  2682.     if (Key = VK_DELETE) or ((Key = VK_INSERT) and (ssShift in Shift)) then
  2683.       FDataLink.Edit;
  2684.   end;
  2685. end;
  2686. procedure TbsSkinDBMemo2.KeyPress(var Key: Char);
  2687. begin
  2688.   inherited KeyPress(Key);
  2689.   if FMemoLoaded then
  2690.   begin
  2691.     if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
  2692.       not FDataLink.Field.IsValidChar(Key) then
  2693.     begin
  2694.       MessageBeep(0);
  2695.       Key := #0;
  2696.     end;
  2697.     case Key of
  2698.       ^H, ^I, ^J, ^M, ^V, ^X, #32..#255:
  2699.         FDataLink.Edit;
  2700.       #27:
  2701.         FDataLink.Reset;
  2702.     end;
  2703.   end else
  2704.   begin
  2705.     if Key = #13 then LoadMemo;
  2706.     Key := #0;
  2707.   end;
  2708. end;
  2709. procedure TbsSkinDBMemo2.Change;
  2710. begin
  2711.   if FMemoLoaded then FDataLink.Modified;
  2712.   FMemoLoaded := True;
  2713.   inherited Change;
  2714. end;
  2715. function TbsSkinDBMemo2.GetDataSource: TDataSource;
  2716. begin
  2717.   Result := FDataLink.DataSource;
  2718. end;
  2719. procedure TbsSkinDBMemo2.SetDataSource(Value: TDataSource);
  2720. begin
  2721.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  2722.     FDataLink.DataSource := Value;
  2723.   if Value <> nil then Value.FreeNotification(Self);
  2724. end;
  2725. function TbsSkinDBMemo2.GetDataField: string;
  2726. begin
  2727.   Result := FDataLink.FieldName;
  2728. end;
  2729. procedure TbsSkinDBMemo2.SetDataField(const Value: string);
  2730. begin
  2731.   FDataLink.FieldName := Value;
  2732. end;
  2733. function TbsSkinDBMemo2.GetReadOnly: Boolean;
  2734. begin
  2735.   Result := FDataLink.ReadOnly;
  2736. end;
  2737. procedure TbsSkinDBMemo2.SetReadOnly(Value: Boolean);
  2738. begin
  2739.   FDataLink.ReadOnly := Value;
  2740. end;
  2741. function TbsSkinDBMemo2.GetField: TField;
  2742. begin
  2743.   Result := FDataLink.Field;
  2744. end;
  2745. procedure TbsSkinDBMemo2.LoadMemo;
  2746. begin
  2747.   if not FMemoLoaded and Assigned(FDataLink.Field) and FDataLink.Field.IsBlob then
  2748.   begin
  2749.     try
  2750.       Lines.Text := FDataLink.Field.AsString;
  2751.       FMemoLoaded := True;
  2752.     except
  2753.       { Memo too large }
  2754.       on E:EInvalidOperation do
  2755.         Lines.Text := Format('(%s)', [E.Message]);
  2756.     end;
  2757.     EditingChange(Self);
  2758.   end;
  2759. end;
  2760. procedure TbsSkinDBMemo2.DataChange(Sender: TObject);
  2761. begin
  2762.   if FDataLink.Field <> nil then
  2763.     if FDataLink.Field.IsBlob then
  2764.     begin
  2765.       if FAutoDisplay or (FDataLink.Editing and FMemoLoaded) then
  2766.       begin
  2767.         FMemoLoaded := False;
  2768.         LoadMemo;
  2769.       end else
  2770.       begin
  2771.         Text := Format('(%s)', [FDataLink.Field.DisplayLabel]);
  2772.         FMemoLoaded := False;
  2773.       end;
  2774.     end else
  2775.     begin
  2776.       if FFocused and FDataLink.CanModify then
  2777.         Text := FDataLink.Field.Text
  2778.       else
  2779.         Text := FDataLink.Field.DisplayText;
  2780.       FMemoLoaded := True;
  2781.     end
  2782.   else
  2783.   begin
  2784.     if csDesigning in ComponentState then Text := Name else Text := '';
  2785.     FMemoLoaded := False;
  2786.   end;
  2787.   if HandleAllocated then
  2788.     RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ERASE or RDW_FRAME);
  2789. end;
  2790. procedure TbsSkinDBMemo2.EditingChange(Sender: TObject);
  2791. begin
  2792.   inherited ReadOnly := not (FDataLink.Editing and FMemoLoaded);
  2793. end;
  2794. procedure TbsSkinDBMemo2.UpdateData(Sender: TObject);
  2795. begin
  2796.   FDataLink.Field.AsString := Text;
  2797. end;
  2798. procedure TbsSkinDBMemo2.SetFocused(Value: Boolean);
  2799. begin
  2800.   if FFocused <> Value then
  2801.   begin
  2802.     FFocused := Value;
  2803.     if not Assigned(FDataLink.Field) or not FDataLink.Field.IsBlob then
  2804.       FDataLink.Reset;
  2805.   end;
  2806. end;
  2807. procedure TbsSkinDBMemo2.WndProc(var Message: TMessage);
  2808. begin
  2809.   inherited;
  2810. end;
  2811. procedure TbsSkinDBMemo2.CMEnter(var Message: TCMEnter);
  2812. begin
  2813.   SetFocused(True);
  2814.   inherited;
  2815.   if FDataLink.CanModify then
  2816.     inherited ReadOnly := False;
  2817. end;
  2818. procedure TbsSkinDBMemo2.CMExit(var Message: TCMExit);
  2819. begin
  2820.   try
  2821.     FDataLink.UpdateRecord;
  2822.   except
  2823.     SetFocus;
  2824.     raise;
  2825.   end;
  2826.   SetFocused(False);
  2827.   inherited;
  2828. end;
  2829. procedure TbsSkinDBMemo2.SetAutoDisplay(Value: Boolean);
  2830. begin
  2831.   if FAutoDisplay <> Value then
  2832.   begin
  2833.     FAutoDisplay := Value;
  2834.     if Value then LoadMemo;
  2835.   end;
  2836. end;
  2837. procedure TbsSkinDBMemo2.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  2838. begin
  2839.   if not FMemoLoaded then LoadMemo else inherited;
  2840. end;
  2841. procedure TbsSkinDBMemo2.WMCut(var Message: TMessage);
  2842. begin
  2843.   FDataLink.Edit;
  2844.   inherited;
  2845. end;
  2846. procedure TbsSkinDBMemo2.WMUndo(var Message: TMessage);
  2847. begin
  2848.   FDataLink.Edit;
  2849.   inherited;
  2850. end;
  2851. procedure TbsSkinDBMemo2.WMPaste(var Message: TMessage);
  2852. begin
  2853.   FDataLink.Edit;
  2854.   inherited;
  2855. end;
  2856. procedure TbsSkinDBMemo2.CMGetDataLink(var Message: TMessage);
  2857. begin
  2858.   Message.Result := Integer(FDataLink);
  2859. end;
  2860. function TbsSkinDBMemo2.ExecuteAction(Action: TBasicAction): Boolean;
  2861. begin
  2862.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  2863.     FDataLink.ExecuteAction(Action);
  2864. end;
  2865. function TbsSkinDBMemo2.UpdateAction(Action: TBasicAction): Boolean;
  2866. begin
  2867.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  2868.     FDataLink.UpdateAction(Action);
  2869. end;
  2870. constructor TbsSkinDBDateEdit.Create(AOwner: TComponent);
  2871. begin
  2872.   inherited Create(AOwner);
  2873.   ControlStyle := ControlStyle + [csReplicatable];
  2874.   FDataLink := TFieldDataLink.Create;
  2875.   FDataLink.Control := Self;
  2876.   FDataLink.OnDataChange := DataChange;
  2877.   FDataLink.OnEditingChange := EditingChange;
  2878.   FDataLink.OnUpdateData := UpdateData;
  2879.   FInChange := False;
  2880.   FInDataChange := False;
  2881. end;
  2882. destructor TbsSkinDBDateEdit.Destroy;
  2883. begin
  2884.   FDataLink.Free;
  2885.   FDataLink := nil;
  2886.   inherited Destroy;
  2887. end;
  2888. procedure TbsSkinDBDateEdit.Loaded;
  2889. begin
  2890.   inherited Loaded;
  2891.   if (csDesigning in ComponentState) then DataChange(Self);
  2892. end;
  2893. procedure TbsSkinDBDateEdit.Notification(AComponent: TComponent;
  2894.   Operation: TOperation);
  2895. begin
  2896.   inherited Notification(AComponent, Operation);
  2897.   if (Operation = opRemove) and (FDataLink <> nil) and
  2898.     (AComponent = DataSource) then DataSource := nil;
  2899. end;
  2900. procedure TbsSkinDBDateEdit.Reset;
  2901. begin
  2902.   FDataLink.Reset;
  2903.   SelectAll;
  2904. end;
  2905. procedure TbsSkinDBDateEdit.Change;
  2906. begin
  2907.   FInChange := True;
  2908.   if not FInDataChange and (FDataLink <> nil) and
  2909.      not ReadOnly and FDataLink.CanModify
  2910.   then
  2911.     begin
  2912.       if not FDataLink.Editing then FDataLink.Edit;
  2913.       FDataLink.Modified;
  2914.       inherited Change;
  2915.     end;
  2916.   FInChange := False;
  2917. end;
  2918. function TbsSkinDBDateEdit.GetDataSource: TDataSource;
  2919. begin
  2920.   Result := FDataLink.DataSource;
  2921. end;
  2922. procedure TbsSkinDBDateEdit.SetDataSource(Value: TDataSource);
  2923. begin
  2924.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  2925.     FDataLink.DataSource := Value;
  2926.   if Value <> nil then Value.FreeNotification(Self);
  2927. end;
  2928. function TbsSkinDBDateEdit.GetDataField: string;
  2929. begin
  2930.   Result := FDataLink.FieldName;
  2931. end;
  2932. procedure TbsSkinDBDateEdit.SetDataField(const Value: string);
  2933. begin
  2934.   FDataLink.FieldName := Value;
  2935. end;
  2936. function TbsSkinDBDateEdit.GetReadOnly: Boolean;
  2937. begin
  2938.   Result := FDataLink.ReadOnly;
  2939. end;
  2940. procedure TbsSkinDBDateEdit.SetReadOnly(Value: Boolean);
  2941. begin
  2942.   FDataLink.ReadOnly := Value;
  2943. end;
  2944. function TbsSkinDBDateEdit.GetField: TField;
  2945. begin
  2946.   Result := FDataLink.Field;
  2947. end;
  2948. procedure TbsSkinDBDateEdit.DataChange(Sender: TObject);
  2949. begin
  2950.   FInDataChange := True;
  2951.   if not FInChange then
  2952.   if FDataLink.Field <> nil
  2953.   then
  2954.     begin
  2955.       if (FDataLink.Field.Text <> '') and
  2956.       IsValidText(FDataLink.Field.Text)
  2957.       then Date := StrToDate(FDataLink.Field.Text);
  2958.     end;
  2959.   FInDataChange := False;
  2960. end;
  2961. procedure TbsSkinDBDateEdit.EditingChange(Sender: TObject);
  2962. begin
  2963.   inherited ReadOnly := not FDataLink.Editing;
  2964. end;
  2965. procedure TbsSkinDBDateEdit.UpdateData(Sender: TObject);
  2966. begin
  2967.   FDataLink.Field.Text := Text;
  2968. end;
  2969. procedure TbsSkinDBDateEdit.CMEnter;
  2970. begin
  2971.   inherited;
  2972.   if FDataLink.CanModify then
  2973.     inherited ReadOnly := False;
  2974. end;
  2975. procedure TbsSkinDBDateEdit.CMExit;
  2976. begin
  2977.   inherited;
  2978.   if (FDataLink <> nil) and (FDataLink.Editing)
  2979.   then
  2980.     FDataLink.UpdateRecord;
  2981. end;
  2982. procedure TbsSkinDBDateEdit.CMGetDataLink(var Message: TMessage);
  2983. begin
  2984.   Message.Result := Integer(FDataLink);
  2985. end;
  2986. function TbsSkinDBDateEdit.ExecuteAction(Action: TBasicAction): Boolean;
  2987. begin
  2988.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  2989.     FDataLink.ExecuteAction(Action);
  2990. end;
  2991. function TbsSkinDBDateEdit.UpdateAction(Action: TBasicAction): Boolean;
  2992. begin
  2993.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  2994.     FDataLink.UpdateAction(Action);
  2995. end;
  2996. //////////////////////////////////////////////////////////////////////////////
  2997. constructor TbsSkinDBTimeEdit.Create(AOwner: TComponent);
  2998. begin
  2999.   inherited Create(AOwner);
  3000.   ControlStyle := ControlStyle + [csReplicatable];
  3001.   FDataLink := TFieldDataLink.Create;
  3002.   FDataLink.Control := Self;
  3003.   FDataLink.OnDataChange := DataChange;
  3004.   FDataLink.OnEditingChange := EditingChange;
  3005.   FDataLink.OnUpdateData := UpdateData;
  3006.   FInChange := False;
  3007.   FInDataChange := False;
  3008. end;
  3009. destructor TbsSkinDBTimeEdit.Destroy;
  3010. begin
  3011.   FDataLink.Free;
  3012.   FDataLink := nil;
  3013.   inherited Destroy;
  3014. end;
  3015. procedure TbsSkinDBTimeEdit.Loaded;
  3016. begin
  3017.   inherited Loaded;
  3018.   if (csDesigning in ComponentState) then DataChange(Self);
  3019. end;
  3020. procedure TbsSkinDBTimeEdit.Notification(AComponent: TComponent;
  3021.   Operation: TOperation);
  3022. begin
  3023.   inherited Notification(AComponent, Operation);
  3024.   if (Operation = opRemove) and (FDataLink <> nil) and
  3025.     (AComponent = DataSource) then DataSource := nil;
  3026. end;
  3027. procedure TbsSkinDBTimeEdit.Reset;
  3028. begin
  3029.   FDataLink.Reset;
  3030.   SelectAll;
  3031. end;
  3032. procedure TbsSkinDBTimeEdit.Change;
  3033. begin
  3034.   FInChange := True;
  3035.   if not FInDataChange and (FDataLink <> nil) and
  3036.      not ReadOnly and FDataLink.CanModify
  3037.   then
  3038.     begin
  3039.       if not FDataLink.Editing then FDataLink.Edit;
  3040.       FDataLink.Modified;
  3041.       inherited Change;
  3042.     end;
  3043.   FInChange := False;
  3044. end;
  3045. function TbsSkinDBTimeEdit.GetDataSource: TDataSource;
  3046. begin
  3047.   Result := FDataLink.DataSource;
  3048. end;
  3049. procedure TbsSkinDBTimeEdit.SetDataSource(Value: TDataSource);
  3050. begin
  3051.   if not (FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
  3052.     FDataLink.DataSource := Value;
  3053.   if Value <> nil then Value.FreeNotification(Self);
  3054. end;
  3055. function TbsSkinDBTimeEdit.GetDataField: string;
  3056. begin
  3057.   Result := FDataLink.FieldName;
  3058. end;
  3059. procedure TbsSkinDBTimeEdit.SetDataField(const Value: string);
  3060. begin
  3061.   FDataLink.FieldName := Value;
  3062. end;
  3063. function TbsSkinDBTimeEdit.GetReadOnly: Boolean;
  3064. begin
  3065.   Result := FDataLink.ReadOnly;
  3066. end;
  3067. procedure TbsSkinDBTimeEdit.SetReadOnly(Value: Boolean);
  3068. begin
  3069.   FDataLink.ReadOnly := Value;
  3070. end;
  3071. function TbsSkinDBTimeEdit.GetField: TField;
  3072. begin
  3073.   Result := FDataLink.Field;
  3074. end;
  3075. procedure TbsSkinDBTimeEdit.DataChange(Sender: TObject);
  3076. begin
  3077.   FInDataChange := True;
  3078.   if not FInChange then
  3079.   if FDataLink.Field <> nil
  3080.   then
  3081.     Text := FDataLink.Field.Text;
  3082.   FInDataChange := False;
  3083. end;
  3084. procedure TbsSkinDBTimeEdit.EditingChange(Sender: TObject);
  3085. begin
  3086.   inherited ReadOnly := not FDataLink.Editing;
  3087. end;
  3088. procedure TbsSkinDBTimeEdit.UpdateData(Sender: TObject);
  3089. begin
  3090.   FDataLink.Field.Text := Text;
  3091. end;
  3092. procedure TbsSkinDBTimeEdit.CMEnter;
  3093. begin
  3094.   inherited;
  3095.   if FDataLink.CanModify then
  3096.     inherited ReadOnly := False;
  3097. end;
  3098. procedure TbsSkinDBTimeEdit.CMExit;
  3099. begin
  3100.   inherited;
  3101.   if (FDataLink <> nil) and (FDataLink.Editing)
  3102.   then
  3103.     FDataLink.UpdateRecord;
  3104. end;
  3105. procedure TbsSkinDBTimeEdit.CMGetDataLink(var Message: TMessage);
  3106. begin
  3107.   Message.Result := Integer(FDataLink);
  3108. end;
  3109. function TbsSkinDBTimeEdit.ExecuteAction(Action: TBasicAction): Boolean;
  3110. begin
  3111.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  3112.     FDataLink.ExecuteAction(Action);
  3113. end;
  3114. function TbsSkinDBTimeEdit.UpdateAction(Action: TBasicAction): Boolean;
  3115. begin
  3116.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  3117.     FDataLink.UpdateAction(Action);
  3118. end;
  3119. end.