home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / WIN / Programa / CASCCONT.ZIP / COMPON / DBRXEDIT.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1996-09-08  |  23.2 KB  |  756 lines

  1. unit DbRXEdit;
  2. {
  3.   Version 1.0
  4.  
  5.   Freeware
  6.   An exploding data-aware RTF memo component with popup to
  7.   change fonts.
  8.  
  9.   Using Helmut Tammen's (German) and James Gabriel's (English)
  10.   component, who based their's on Borland-code.
  11.   Modified to explode on click by Dieter Menne, 100016.2125@compuserve.com
  12.   Also, some anomalities corrected (=bugs removed) and
  13.   some "works-as-designed" features added (= new bugs introduced).
  14.   This version is used in DBCasc-Controls.
  15.   Currently, I can't get it to work with Cached Updates.
  16.   This is a reported bug in version of the BDE coming with Delphi 2.0 supposed
  17.   to be corrected in 2.01, but I could not test this version yet.
  18.   Almost all comments are by D.M.
  19.  }
  20. interface
  21.  
  22. uses
  23.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  24.   StdCtrls, ComCtrls,DB,DBCtrls,Menus,DBTables;
  25.  
  26. const USER_SETFOCUS=WM_USER+100;
  27.  
  28. type
  29.     { TDbRXEdit }
  30.   TDbRXEdit = class(TRichEdit)
  31.   private
  32.     FOnExplode,
  33.     FOnCollapse: TNotifyEvent;
  34.     FDataLink: TFieldDataLink;
  35.     FIsExploded, FAutoExplode,
  36.     FAutoDisplay,
  37.     FFocused,
  38.     FMemoLoaded: Boolean;
  39.     FSelStart: Integer;
  40.     FPaintControl: TPaintControl;
  41.     FPopup: TPopupMenu;
  42.     FExLeft,FExTop,FExWidth,FExHeight: integer;
  43.     FDefLeft,FDefTop,FDefWidth,FDefHeight: integer;
  44.     FDefParent: TWinControl;
  45.  
  46.     procedure DataChange(Sender: TObject);
  47.     procedure EditingChange(Sender: TObject);
  48.     procedure EditDataLink;
  49.     function GetDataField: string;
  50.     function GetDataSource: TDataSource;
  51.     function GetField: TField;
  52.     function GetReadOnly: Boolean;
  53.     procedure SetDataField(const Value: string);
  54.     procedure SetDataSource(Value: TDataSource);
  55.     procedure SetReadOnly(Value: Boolean);
  56.     procedure SetAutoDisplay(Value: Boolean);
  57.     procedure SetFocused(Value: Boolean);
  58.  
  59.     procedure UpdateData(Sender: TObject);
  60.  
  61.     procedure UserSetFocus(var Mess: TMessage); message USER_SETFOCUS;
  62.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  63.     procedure WMCut(var Message: TMessage); message WM_CUT;
  64.     procedure WMPaste(var Message: TMessage); message WM_PASTE;
  65.     procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
  66.     procedure CMExit(var Message: TCMExit); message CM_EXIT;
  67.     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  68.     procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
  69.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  70.     procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK;
  71.  
  72.     procedure ProcessKey( Key: Char );
  73.     procedure CreatePopupMenu;
  74.     procedure FPopupOnPopup( Sender: TObject );
  75.     procedure MenuClickBold( Sender: TObject );
  76.     procedure MenuClickItalic( Sender: TObject );
  77.     procedure MenuClickUnderline( Sender: TObject );
  78.     procedure MenuClickStrikeout( Sender: TObject );
  79.     procedure MenuClickFont( Sender: TObject );
  80.  
  81.     procedure SetExploded(Value: boolean);
  82.     procedure StoreExSize;
  83.     procedure WMMove( var Msg : TWMMove ) ; message WM_MOVE ;
  84.     procedure WMSize( var Msg : TWMSize ) ; message WM_SIZE ;
  85.  
  86.   protected
  87.     procedure Change; override;
  88.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  89.     procedure KeyPress(var Key: Char); override;
  90.     procedure Notification(AComponent: TComponent;
  91.                           Operation: TOperation); override;
  92.     procedure WndProc(var Message: TMessage); override;
  93.     procedure Loaded; override;
  94.  
  95.   public
  96.     constructor Create(AOwner: TComponent); override;
  97.     destructor Destroy; override;
  98.     procedure Explode;virtual;
  99.     procedure Collapse;virtual;
  100.     procedure LoadMemo;
  101.     property Field: TField read GetField;
  102.  
  103.   published
  104.     property Align;
  105.     property Alignment;
  106.     property AutoDisplay: Boolean read FAutoDisplay write SetAutoDisplay default True;
  107.     property BorderStyle;
  108.     property Color;
  109.     property Ctl3D;
  110.     property DataField: string read GetDataField write SetDataField;
  111.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  112.     property DragCursor;
  113.     property DragMode;
  114.     property AutoExplode: boolean read FAutoExplode write FAutoExplode;
  115.     property ExLeft:   integer read FExLeft write FExLeft;
  116.     property ExTop:    integer read FExTop write FExTop;
  117.     property ExWidth:  integer read FExWidth write FExWidth;
  118.     property ExHeight: integer read FExHeight write FExHeight;
  119.     // The idea of setting stored = false was to avoid storing an exploded
  120.     // state of the edit field. It seems not to work as expected, though
  121.     property Exploded: boolean read FIsExploded write SetExploded stored False;
  122.     property Enabled;
  123.     property Font;
  124.     property MaxLength;
  125.     property ParentColor;
  126.     property ParentCtl3D;
  127.     property ParentFont;
  128.     property ParentShowHint;
  129.     property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
  130.     property ScrollBars;
  131.     property ShowHint;
  132.     property TabOrder;
  133.     property TabStop;
  134.     property Visible;
  135.     property WantTabs;
  136.     property WordWrap;
  137.     property OnChange;
  138.     property OnClick;
  139.     property OnCollapse: TNotifyEvent read FOnCollapse write FOnCollapse;
  140.     property OnDblClick;
  141.     property OnDragDrop;
  142.     property OnDragOver;
  143.     property OnExplode: TNotifyEvent read FOnExplode write FOnExplode;
  144.     property OnEndDrag;
  145.     property OnEnter;
  146.     property OnExit;
  147.     property OnKeyDown;
  148.     property OnKeyPress;
  149.     property OnKeyUp;
  150.     property OnMouseDown;
  151.     property OnMouseMove;
  152.     property OnMouseUp;
  153.     property OnStartDrag;
  154.   end;
  155.  
  156. procedure Register;
  157.  
  158. { ----------------------------- implementation --------------------------------}
  159. implementation
  160.  
  161. uses DBConsts;
  162.  
  163. { -------------------------- Create -------------------------------------------}
  164. constructor TDbRXEdit.Create(AOwner: TComponent);
  165. begin
  166.   inherited Create(AOwner);
  167.   inherited ReadOnly := True;
  168.   FIsExploded:=False;
  169.   FAutoDisplay := True;
  170.   FAutoExplode:=True;
  171.   FDataLink := TFieldDataLink.Create;
  172.   FDataLink.Control := Self;
  173.   FDataLink.OnDataChange := DataChange;
  174.   FDataLink.OnEditingChange := EditingChange;
  175.   FDataLink.OnUpdateData := UpdateData;
  176.   FPaintControl := TPaintControl.Create(Self, 'RICHEDIT');
  177.  
  178.   Height:=21; // We start with a small size
  179.   Width:=121;
  180.   if not (csDesigning in ComponentState) then
  181.     CreatePopupMenu();
  182. end;
  183.  
  184. { ------------------------------ Loaded ---------------------------------------}
  185. procedure TDbRXEdit.Loaded;
  186. begin
  187.   inherited Loaded;
  188.   // Can anybody tell me how I can inhibit storing of exploded states?
  189.   if Exploded then  // Should not happen, because we don't store it
  190.     raise Exception.Create('DbRXEdit or CascMemo stored in exploded state');
  191. end;
  192.  
  193. { ------------------------------ Destroy ---------------------------------------}
  194. destructor TDbRXEdit.Destroy;
  195. begin
  196.   if FPopup <> nil then
  197.   begin
  198.     FPopup.OnPopup := nil;
  199.     FPopup.Free;
  200.   end;
  201.   FPaintControl.Free;
  202.   FDataLink.Free;
  203.   FDataLink := nil;
  204.   inherited Destroy;
  205. end;
  206.  
  207. { --------------------------- CreatePopupMenu ---------------------------------}
  208. procedure TDbRXEdit.CreatePopupMenu;
  209. begin
  210.   FPopup := TPopupMenu.Create( self );
  211.   { Thanks to Robert Vivrette's Unofficial Newletter to remind me
  212.     of this shortcut }
  213.   with FPopup.Items do
  214.   begin
  215.     Add(NewItem('&Bold',0,False,True,MenuClickBold,0,'MenuItem1'));
  216.     Add(NewItem('&Italic',0,False,True,MenuClickItalic,0,'MenuItem2'));
  217.     Add(NewItem('&Underline',0,False,True,MenuClickUnderline,0,'MenuItem3'));
  218.     Add(NewItem('&Strikeout',0,False,True,MenuClickUnderline,0,'MenuItem4'));
  219.     Add(NewLine);
  220.     Add(NewItem('&Fonts',0,False,True,MenuClickFont,0,'MenuItem5'));
  221.   end;
  222.   FPopup.OnPopup := FPopupOnPopup;
  223.   PopupMenu := FPopup;
  224. end;
  225.  
  226.  
  227. { ----------------------------- Notification  ---------------------------------}
  228. procedure TDbRXEdit.Notification(AComponent: TComponent;
  229.   Operation: TOperation);
  230. begin
  231.   inherited Notification(AComponent, Operation);
  232.   if (Operation = opRemove) and (FDataLink <> nil) and
  233.      (AComponent = DataSource) then DataSource := nil;
  234.  
  235. end;
  236.  
  237. { ---------------------------- EditDataLink -----------------------------------}
  238. procedure TDbRXEdit.EditDataLink;
  239. var SStart,SLength: integer;
  240. begin
  241.   { Changed, D.M.}
  242.   if FDataLink.Editing then exit;
  243.   { Keep selection and caret position }
  244.   SStart:=SelStart;  SLength:=SelLength;
  245.   FDataLink.Edit;
  246.   { Restore Selection }
  247.   SelStart:=SStart;  SelLength:=SLength;
  248. end;
  249.  
  250. { ------------------------------ KeyDown --------------------------------------}
  251. procedure TDbRXEdit.KeyDown(var Key: Word; Shift: TShiftState);
  252. begin
  253.   inherited KeyDown(Key, Shift);
  254.   if FMemoLoaded then
  255.   begin
  256.       if (Key = VK_DELETE) or ((Key = VK_INSERT) and (ssShift in Shift)) then
  257.           EditDataLink;
  258.   end else
  259.       Key := 0;
  260. end;
  261.  
  262. { ------------------------------ KeyPress -------------------------------------}
  263. procedure TDbRXEdit.KeyPress(var Key: Char);
  264. begin
  265.   inherited KeyPress(Key);
  266.   if FMemoLoaded then
  267.   begin
  268.       if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
  269.            not FDataLink.Field.IsValidChar(Key) then
  270.      begin
  271.           MessageBeep(0);
  272.          Key := #0;
  273.      end;
  274.      case Key of
  275.          ^H, ^J, ^M, ^V, ^X, #32..#255:
  276.            EditDataLink;
  277.          ^B, ^I, ^U, ^S:
  278.           begin
  279.                 EditDataLink;
  280.                  ProcessKey( Key );
  281.             end;
  282.         #27:
  283.           FDataLink.Reset;
  284.      end;
  285.   end  else
  286.   begin  { Memo not yet loaded }
  287.      if Key = #13 then LoadMemo;
  288.      Key := #0;
  289.   end;
  290. end;
  291.  
  292. { ------------------------------ Change ---------------------------------------}
  293. procedure TDbRXEdit.Change;
  294. begin
  295.   if FMemoLoaded then FDataLink.Modified;
  296.   //FMemoLoaded := True; { Why in original code?? D.M.}
  297.   inherited Change;
  298. end;
  299.  
  300. { ------------------------- Get/SetDataSource ---------------------------------}
  301. function TDbRXEdit.GetDataSource: TDataSource;
  302. begin
  303.   Result := FDataLink.DataSource;
  304. end;
  305.  
  306. procedure TDbRXEdit.SetDataSource(Value: TDataSource);
  307. begin
  308.   FDataLink.DataSource := Value;
  309.   if Value <> nil then Value.FreeNotification(Self);
  310. end;
  311.  
  312. { ------------------------- Get/SetDataField ----------------------------------}
  313. function TDbRXEdit.GetDataField: string;
  314. begin
  315.   Result := FDataLink.FieldName;
  316. end;
  317.  
  318. procedure TDbRXEdit.SetDataField(const Value: string);
  319. begin
  320.   FDataLink.FieldName := Value;
  321. end;
  322.  
  323. { ------------------------------ GetReadOnly ----------------------------------}
  324. function TDbRXEdit.GetReadOnly: Boolean;
  325. begin
  326.   Result := FDataLink.ReadOnly;
  327. end;
  328.  
  329. procedure TDbRXEdit.SetReadOnly(Value: Boolean);
  330. begin
  331.   FDataLink.ReadOnly := Value;
  332. end;
  333.  
  334. { ------------------------------ GetField -------------------------------------}
  335. function TDbRXEdit.GetField: TField;
  336. begin
  337.   Result := FDataLink.Field;
  338. end;
  339.  
  340. { ------------------------------ LoadMemo -------------------------------------}
  341. procedure TDbRXEdit.LoadMemo;
  342. var
  343.     BlobStream: TBlobStream;
  344. begin
  345.   if FMemoLoaded or not (FDataLink.Field is TBlobField) then exit;
  346.   try
  347.     BlobStream:= TBlobStream.create( TBlobField(FDataLink.Field), bmRead );
  348.     Lines.loadfromstream(BlobStream);
  349.         BlobStream.free;
  350.         FMemoLoaded := True;
  351.      except
  352.       on E:Exception do
  353.     // Message "this is not a blob" comes up when using Cached Updates
  354.     // with the version of the BDE coming with Delphi 2.0 (D.M)
  355.         ShowMessage(E.Message+' ('+FDataLink.FieldName+
  356.     '). Are you using cached updates with the BDE coming with D2.0?');
  357.     end;
  358.      EditingChange(Self);
  359. end;
  360.  
  361. { --------------------------- DataChange --------------------------------------}
  362. procedure TDbRXEdit.DataChange(Sender: TObject);
  363. var SStart,SLength: integer;
  364.     WasLoaded: boolean;
  365. begin
  366.   if FDataLink.Field <> nil then
  367.      if FDataLink.Field is TBlobField then
  368.      begin
  369.         if FAutoDisplay or (FDataLink.Editing and FMemoLoaded) then
  370.         begin
  371.       { Keep selection and caret position }
  372.       { The solution used here is not perfect, but somewhat
  373.       better than that in the original Borland Memo where
  374.       the caret jumps confusingly even on trivial
  375.       edit state changes. D.M.}
  376.       WasLoaded:=FMemoLoaded;
  377.       SStart:=SelStart;
  378.       SLength:=SelLength;
  379.       { Force loading }
  380.           FMemoLoaded := False;
  381.           LoadMemo;
  382.       { Restore Selection }
  383.       if WasLoaded then
  384.       begin
  385.         SelStart:=SStart;
  386.         SelLength:=SLength;
  387.       end;
  388.         end else
  389.         begin
  390.           Text := '(' + FDataLink.Field.DisplayLabel + ')';
  391.           FMemoLoaded := False;
  392.         end;
  393.      end else
  394.      begin
  395.         if FFocused and FDataLink.CanModify then
  396.           Text := FDataLink.Field.Text
  397.         else
  398.           Text := FDataLink.Field.DisplayText;
  399.         FMemoLoaded := True;
  400.      end
  401.   else
  402.   begin
  403.       if csDesigning in ComponentState then Text := Name else Text := '';
  404.       FMemoLoaded := False;
  405.   end;
  406. end;
  407.  
  408. { --------------------------- EditingChange -----------------------------------}
  409. procedure TDbRXEdit.EditingChange(Sender: TObject);
  410. begin
  411.   inherited ReadOnly := not (FDataLink.Editing and FMemoLoaded);
  412. end;
  413.  
  414. { --------------------------- UpdateData --------------------------------------}
  415. procedure TDbRXEdit.UpdateData(Sender: TObject);
  416. var
  417.     BlobStream: TBlobStream;
  418. begin
  419.     BlobStream:= TBlobStream.create( TBlobField( FDataLink.Field ), bmReadWrite );
  420.     Lines.savetostream(BlobStream);
  421.     BlobStream.free;
  422. end;
  423.  
  424. { ---------------------------- SetFocused -------------------------------------}
  425. procedure TDbRXEdit.SetFocused(Value: Boolean);
  426. begin
  427.   if FFocused <> Value then
  428.   begin
  429.       FFocused := Value;
  430.       if not (FDataLink.Field is TBlobField) then FDataLink.Reset;
  431.   end;
  432. end;
  433.  
  434. { ------------------------------ WndProc --------------------------------------}
  435. procedure TDbRXEdit.WndProc(var Message: TMessage);
  436. begin
  437.   with Message do
  438.       if (Msg = WM_CREATE) or (Msg = WM_WINDOWPOSCHANGED) or
  439.          (Msg = CM_FONTCHANGED) then FPaintControl.DestroyHandle;
  440.   inherited;
  441. end;
  442.  
  443. { ------------------------------ CMEnter --------------------------------------}
  444. procedure TDbRXEdit.CMEnter(var Message: TCMEnter);
  445. begin
  446.   if AutoExplode then Explode; { Even if this is done in WMLButtonClick,
  447.   we need it here too for tabbing. Luckily, Explode immediately
  448.   returns if it is already done, so not much is lost.}
  449.   SetFocused(True);
  450.   inherited;
  451. end;
  452.  
  453. { ------------------------------ CMExit ---------------------------------------}
  454. procedure TDbRXEdit.CMExit(var Message: TCMExit);
  455. begin
  456.   // I would like to get rid of the extra Editing test, but
  457.   // when it's missing I get "Dataset not in Edit mode" on leaving
  458.   // the Editor with tab.
  459.   if (FDataLink.Field is TBlobField) and (FDataLink.Editing) then
  460.   try
  461.         FDataLink.UpdateRecord;
  462.   except
  463.        SetFocus;
  464.         raise;
  465.     end;
  466.   SetFocused(False);
  467.   inherited;
  468. end;
  469.  
  470. { ----------------------- SetAutoDisplay --------------------------------------}
  471. procedure TDbRXEdit.SetAutoDisplay(Value: Boolean);
  472. begin
  473.   if FAutoDisplay <> Value then
  474.   begin
  475.      FAutoDisplay := Value;
  476.      if Value then LoadMemo;
  477.   end;
  478. end;
  479.  
  480. { ------------------------ WMLButtonDblClk ------------------------------------}
  481. procedure TDbRXEdit.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  482. begin
  483.   if not FMemoLoaded then LoadMemo else inherited;
  484. end;
  485.  
  486.  
  487. { ------------------------ WMLButtonDown --------------------------------------}
  488. procedure TDbRXEdit.WMLButtonDown(var Message: TWMLButtonDown);
  489. begin
  490.   inherited;
  491.   if  not (csDesigning in ComponentState) and FAutoExplode then
  492.     Explode; { Doing' this in WMEnter should be
  493.                enuff, but it leads to an address violation.
  494.                If anyone knows why? D.M.}
  495. end;
  496.  
  497.  
  498. { -------------------------- WMKillFocus --------------------------------------}
  499. procedure TDbRXEdit.WMKillFocus(var Message: TWMKillFocus);
  500. begin
  501.   // Collapse when focus goes to another control
  502.   inherited;
  503.   if FAutoExplode then Collapse;
  504. end;
  505.  
  506. { ------------------------------ WMCut ----------------------------------------}
  507. procedure TDbRXEdit.WMCut(var Message: TMessage);
  508. begin
  509.   EditDataLink;
  510.   inherited;
  511. end;
  512.  
  513. { ------------------------------ WMPaste --------------------------------------}
  514. procedure TDbRXEdit.WMPaste(var Message: TMessage);
  515. begin
  516.   EditDataLink;
  517.   inherited;
  518. end;
  519.  
  520. { --------------------------- CMGetDataLink -----------------------------------}
  521. procedure TDbRXEdit.CMGetDataLink(var Message: TMessage);
  522. begin
  523.   Message.Result := Integer(FDataLink);
  524. end;
  525.  
  526. { ---------------------------- WMPaint  ---------------------------------------}
  527. procedure TDbRXEdit.WMPaint(var Message: TWMPaint);
  528. var
  529.   S: string;
  530. begin
  531.   if not (csPaintCopy in ControlState) then inherited else
  532.   begin
  533.      if FDataLink.Field <> nil then
  534.         if FDataLink.Field is TBlobField then
  535.           S := AdjustLineBreaks(FDataLink.Field.AsString) else
  536.           S := FDataLink.Field.DisplayText;
  537.      SendMessage(FPaintControl.Handle, WM_SETTEXT, 0, Integer(PChar(S)));
  538.      SendMessage(FPaintControl.Handle, WM_PAINT, Message.DC, 0);
  539.   end;
  540. end;
  541.  
  542. { ---------------------------- ProcessKey  ------------------------------------}
  543. procedure TDbRXEdit.ProcessKey( Key: Char );
  544. begin
  545.     case Key of
  546.         ^B:
  547.             begin
  548.                 if fsBold in SelAttributes.Style then
  549.                     SelAttributes.Style := SelAttributes.Style - [fsBold]
  550.                 else
  551.                     SelAttributes.Style := SelAttributes.Style + [fsBold];
  552.             end;
  553.         ^I:
  554.             begin
  555.                 if fsItalic in SelAttributes.Style then
  556.                     SelAttributes.Style := SelAttributes.Style - [fsItalic]
  557.                 else
  558.                     SelAttributes.Style := SelAttributes.Style + [fsItalic];
  559.             end;
  560.         ^U:
  561.             begin
  562.                 if fsUnderline in SelAttributes.Style then
  563.                     SelAttributes.Style := SelAttributes.Style - [fsUnderline]
  564.                 else
  565.                     SelAttributes.Style := SelAttributes.Style + [fsUnderline];
  566.             end;
  567.         ^S:
  568.             begin
  569.                 if fsStrikeout in SelAttributes.Style then
  570.                     SelAttributes.Style := SelAttributes.Style - [fsStrikeout]
  571.                 else
  572.                     SelAttributes.Style := SelAttributes.Style + [fsStrikeout];
  573.             end;
  574.     end;
  575. end;
  576.  
  577. { --------------------------- MenuClickFont  ----------------------------------}
  578. procedure TDbRXEdit.MenuClickFont( Sender: TObject );
  579. var
  580.     dlg: TFontDialog;
  581.   SStart,SLength: integer;
  582. begin
  583.   SStart:=SelStart;  { Why does the f... selction disapear? }
  584.   SLength:=SelLength;
  585.  
  586.     dlg := TFontDialog.Create( self );
  587.     dlg.Font.Name := SelAttributes.Name;
  588.     dlg.Font.Color := SelAttributes.Color;
  589.     dlg.Font.Pitch := SelAttributes.Pitch;
  590.     dlg.Font.Size := SelAttributes.Size;
  591.     dlg.Font.Style := SelAttributes.Style;
  592.     dlg.Font.Height := SelAttributes.Height;
  593.  
  594.     if dlg.Execute() then begin
  595.     EditDataLink;
  596.     SelStart:=SStart;
  597.     SelLength:=SLength;
  598.         SelAttributes.Name := dlg.Font.Name;
  599.         SelAttributes.Color := dlg.Font.Color;
  600.         SelAttributes.Pitch := dlg.Font.Pitch;
  601.         SelAttributes.Size := dlg.Font.Size;
  602.         SelAttributes.Style := dlg.Font.Style;
  603.         SelAttributes.Height := dlg.Font.Height;
  604.     end;
  605.     dlg.Free;
  606. end;
  607.  
  608.  
  609. { ------------------------- FPopupOnPopup -------------------------------------}
  610. procedure TDbRXEdit.FPopupOnPopup( Sender: TObject );
  611. begin
  612.   { Replaces the convoluted "if" code in original Borland source.}
  613.     FPopup.Items[0].Checked := fsBold      in SelAttributes.Style;
  614.   FPopup.Items[1].Checked := fsItalic    in SelAttributes.Style;
  615.     FPopup.Items[2].Checked := fsUnderline in SelAttributes.Style;
  616.     FPopup.Items[3].Checked := fsStrikeout in SelAttributes.Style;
  617. end;
  618.  
  619. { -------------------------- MenuClickBold ------------------------------------}
  620. procedure TDbRXEdit.MenuClickBold( Sender: TObject );
  621. var Key:Char;
  622. begin
  623.   Key:=^B;
  624.     KeyPress( Key );
  625. end;
  626.  
  627. { ----------------------------MenuClickItalic  --------------------------------}
  628. procedure TDbRXEdit.MenuClickItalic( Sender: TObject );
  629. var
  630.     Key: Char;
  631. begin
  632.     Key := ^I;
  633.     KeyPress( Key );
  634. end;
  635.  
  636. { ------------------------ MenuClickUnderline ---------------------------------}
  637. procedure TDbRXEdit.MenuClickUnderline( Sender: TObject );
  638. var
  639.     Key: Char;
  640. begin
  641.     Key := ^U;
  642.     KeyPress( Key );
  643. end;
  644.  
  645. { ------------------------  MenuClickStrikeout  -------------------------------}
  646. procedure TDbRXEdit.MenuClickStrikeout( Sender: TObject );
  647. var
  648.     Key: Char;
  649. begin
  650.     Key := ^S;
  651.     KeyPress( Key );
  652. end;
  653.  
  654. { -------------------------- StoreExSize --------------------------------------}
  655. procedure TDbRXEdit.StoreExSize;
  656. begin
  657.   { On designing, we copy the exploded size when collapsing }
  658.   if csDesigning in ComponentState then
  659.   begin
  660.     ExLeft:=Left-FDefParent.Left;
  661.     ExTop:=Top-FDefParent.Top;
  662.     ExWidth:=Width;
  663.     ExHeight:=Height;
  664.   end;
  665. end;
  666.  
  667. { ------------------------------ WMMove ---------------------------------------}
  668. procedure TDbRXEdit.WMMove( var Msg : TWMMove ) ;
  669. begin
  670.   inherited ;
  671.   if FIsExploded then StoreExSize;
  672. end ;
  673.  
  674. { ------------------------------ WMSize ---------------------------------------}
  675. procedure TDbRXEdit.WMSize( var Msg : TWMSize ) ;
  676. begin
  677.   inherited ;
  678.   if FIsExploded then  StoreExSize;
  679. end ;
  680.  
  681. { -------------------------- SetExploded  -------------------------------------}
  682. procedure TDbRXEdit.SetExploded(Value: boolean);
  683. begin
  684.   if Value=FIsExploded then exit; { Nothing to do }
  685.   if Value then
  686.   begin
  687.     { Set a default Exploded width and Height if nothing set }
  688.     if FExWidth< Width then FExWidth:=2*Width;
  689.     if FExHeight< Height then FExHeight:=2*Height;
  690.     Explode;
  691.   end
  692.   else
  693.     Collapse;
  694. end;
  695.  
  696. { -------------------------- UserSetFocus -------------------------------------}
  697. procedure TDbRXEdit.UserSetFocus(var Mess: TMessage);
  698. begin
  699.   { We get this message posted on explode. Make sure that
  700.    the caret gets visible immediately at the right position }
  701.   Windows.SetFocus(Handle);
  702.   SelStart:=FSelStart;
  703. end;
  704.  
  705. { -------------------------- Explode ------------------------------------------}
  706. procedure TDbRXEdit.Explode;
  707. begin
  708.   { Anything to do?}
  709.   if FIsExploded then exit;
  710.   if Assigned(FOnExplode) then FOnExplode(self);
  711.  
  712.   { Stores the current position values }
  713.   FDefLeft:=Left;
  714.   FDefTop:=Top;
  715.   FDefWidth:=Width;
  716.   FDefHeight:=Height;
  717.   FSelStart:=SelStart;
  718.   FDefParent:=Parent;  { Keep for Collapse }
  719.   { Set Expanded position, correcting for Form's coordinates.}
  720.   Parent:=Owner as TWinControl; { If on panel, allow paint on background form}
  721.   FIsExploded:=True;
  722.   SetBounds(FDefParent.Left+FExLeft,FDefParent.Top+FExTop,
  723.             FExWidth,FExHeight);
  724.   PopupMenu:=FPopup;  // Must reassign because parent may have changed
  725.  
  726.   { Tricky way to assure that the exploded state gets the focus
  727.     if the Owner changed, e.g. when on a label }
  728.   if not (csDesigning in ComponentState) then
  729.     PostMessage(Handle,WM_USER+100,0,0);
  730. end;
  731.  
  732. { ------------------------------ Collapse -------------------------------------}
  733. procedure TDbRXEdit.Collapse;
  734. var Designing: boolean;
  735. begin
  736.   { Anything to do?}
  737.   if Not FIsExploded then exit;
  738.   if Assigned(FOnCollapse) then FOnCollapse(self);
  739.   Designing:=csDesigning in ComponentState;
  740.   StoreExSize;
  741.   Parent      := FDefParent; { Restore limitation to panel }
  742.   PopupMenu   := FPopup;  // Probably not necessary, just to be safe
  743.   if  Designing     then FIsExploded := False;
  744.   SetBounds(FDefLeft,FDefTop,FDefWidth,FDefHeight);
  745.   if  Not Designing then FIsExploded := False;
  746. end;
  747.  
  748. { ------------------------------ Register -------------------------------------}
  749. procedure Register;
  750. begin
  751.   RegisterComponents('Data Controls', [TDbRXEdit]);
  752. end;
  753.  
  754. end.
  755.  
  756.