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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1997, 1998 Master-Bank          }
  6. {                                                       }
  7. {*******************************************************}
  8. unit DBRichEd;
  9. interface
  10. {$IFDEF WIN32}
  11. {$I RX.INC}
  12. uses
  13.   Windows, Messages, ComCtrls, CommCtrl, RichEdit, SysUtils, Classes,
  14.   Graphics, Controls, Menus, StdCtrls, DB, {$IFNDEF RX_D3} DBTables, {$ENDIF}
  15.   RxRichEd, DBCtrls;
  16. type
  17.   TRxDBRichEdit = class(TRxCustomRichEdit)
  18.   private
  19.     FDataLink: TFieldDataLink;
  20.     FUpdating: Boolean;
  21.     FStateChanging: Boolean;
  22.     FMemoLoaded: Boolean;
  23.     FAutoDisplay: Boolean;
  24.     FFocused: Boolean;
  25.     FDataSave: string;
  26.     function GetField: TField;
  27.     function GetDataField: string;
  28.     function GetDataSource: TDataSource;
  29.     function GetReadOnly: Boolean;
  30.     procedure SetReadOnly(Value: Boolean);
  31.     procedure SetDataField(const Value: string);
  32.     procedure SetDataSource(Value: TDataSource);
  33.     procedure SetAutoDisplay(Value: Boolean);
  34.     procedure SetFocused(Value: Boolean);
  35.     procedure DataChange(Sender: TObject);
  36.     procedure UpdateData(Sender: TObject);
  37.     procedure EditingChange(Sender: TObject);
  38.     procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK;
  39.     procedure WMPaste(var Message: TMessage); message WM_PASTE;
  40.     procedure WMCut(var Message: TMessage); message WM_CUT;
  41.     procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
  42.     procedure CMExit(var Message: TCMExit); message CM_EXIT;
  43.     procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
  44.     procedure EMSetCharFormat(var Message: TMessage); message EM_SETCHARFORMAT;
  45.     procedure EMSetParaFormat(var Message: TMessage); message EM_SETPARAFORMAT;
  46.   protected
  47.     procedure Change; override;
  48.     function EditCanModify: Boolean; virtual;
  49.     procedure Loaded; override;
  50.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  51.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  52.     procedure KeyPress(var Key: Char); override;
  53.     procedure SetPlainText(Value: Boolean); override;
  54.   public
  55.     constructor Create(AOwner: TComponent); override;
  56.     destructor Destroy; override;
  57.     procedure LoadMemo; virtual;
  58.     procedure UpdateMemo;
  59. {$IFDEF RX_D4}
  60.     function ExecuteAction(Action: TBasicAction): Boolean; override;
  61.     function UpdateAction(Action: TBasicAction): Boolean; override;
  62.     function UseRightToLeftAlignment: Boolean; override;
  63. {$ENDIF}
  64.     property Field: TField read GetField;
  65.     property Lines;
  66.   published
  67.     property AutoDisplay: Boolean read FAutoDisplay write SetAutoDisplay default True;
  68.     property DataField: string read GetDataField write SetDataField;
  69.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  70.     property Align;
  71.     property Alignment;
  72.     property AllowObjects;
  73. {$IFDEF RX_D3}
  74.     property AllowInPlace;
  75. {$ENDIF}
  76.     property AutoURLDetect;
  77.     property AutoVerbMenu;
  78.     property BorderStyle;
  79.     property Color;
  80.     property Ctl3D;
  81.     property DragCursor;
  82.     property DragMode;
  83.     property Enabled;
  84.     property Font;
  85.     property HideSelection;
  86.     property HideScrollBars;
  87. {$IFDEF RX_D4}
  88.     property Anchors;
  89.     property BiDiMode;
  90.     property Constraints;
  91.     property DragKind;
  92.     property ParentBiDiMode;
  93. {$ENDIF}
  94. {$IFNDEF VER90}
  95.     property ImeMode;
  96.     property ImeName;
  97. {$ENDIF}
  98.     property LangOptions;
  99.     property MaxLength;
  100.     property ParentColor;
  101.     property ParentCtl3D;
  102.     property ParentFont;
  103.     property ParentShowHint;
  104.     property PlainText;
  105.     property PopupMenu;
  106.     property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
  107.     property ScrollBars;
  108.     property ShowHint;
  109.     property SelectionBar;
  110.     property StreamFormat;
  111.     property StreamMode;
  112.     property TabOrder;
  113.     property TabStop default True;
  114.     property Title;
  115.     property UndoLimit;
  116.     property Visible;
  117.     property WantReturns;
  118.     property WantTabs;
  119.     property WordSelection;
  120.     property WordWrap;
  121.     property OnChange;
  122.     property OnClick;
  123.     property OnDblClick;
  124.     property OnDragDrop;
  125.     property OnDragOver;
  126.     property OnEndDrag;
  127.     property OnEnter;
  128.     property OnExit;
  129.     property OnKeyDown;
  130.     property OnKeyPress;
  131.     property OnKeyUp;
  132.     property OnMouseDown;
  133.     property OnMouseMove;
  134.     property OnMouseUp;
  135.     property OnResizeRequest;
  136.     property OnSelectionChange;
  137.     property OnProtectChange; { obsolete }
  138.     property OnProtectChangeEx;
  139.     property OnSaveClipboard;
  140.     property OnStartDrag;
  141. {$IFDEF RX_D5}
  142.     property OnContextPopup;
  143. {$ENDIF}
  144. {$IFDEF RX_D4}
  145.     property OnMouseWheel;
  146.     property OnMouseWheelDown;
  147.     property OnMouseWheelUp;
  148.     property OnEndDock;
  149.     property OnStartDock;
  150. {$ENDIF}
  151.     property OnTextNotFound;
  152. {$IFDEF RX_D3}
  153.     property OnCloseFindDialog;
  154. {$ENDIF}
  155.     property OnURLClick;
  156.   end;
  157. {$ENDIF}
  158. implementation
  159. {$IFDEF WIN32}
  160. { TRxDBRichEdit }
  161. constructor TRxDBRichEdit.Create(AOwner: TComponent);
  162. begin
  163.   inherited Create(AOwner);
  164.   inherited ReadOnly := True;
  165.   FAutoDisplay := True;
  166.   FDataLink := TFieldDataLink.Create;
  167.   FDataLink.Control := Self;
  168.   FDataLink.OnDataChange := DataChange;
  169.   FDataLink.OnEditingChange := EditingChange;
  170.   FDataLink.OnUpdateData := UpdateData;
  171. end;
  172. destructor TRxDBRichEdit.Destroy;
  173. begin
  174.   FDataLink.Free;
  175.   FDataLink := nil;
  176.   inherited Destroy;
  177. end;
  178. procedure TRxDBRichEdit.Loaded;
  179. begin
  180.   inherited Loaded;
  181.   if (csDesigning in ComponentState) then DataChange(Self);
  182. end;
  183. procedure TRxDBRichEdit.Notification(AComponent: TComponent; Operation: TOperation);
  184. begin
  185.   inherited Notification(AComponent, Operation);
  186.   if (Operation = opRemove) and (FDataLink <> nil) and
  187.     (AComponent = DataSource) then DataSource := nil;
  188. end;
  189. {$IFDEF RX_D4}
  190. function TRxDBRichEdit.UseRightToLeftAlignment: Boolean;
  191. begin
  192.   Result := DBUseRightToLeftAlignment(Self, Field);
  193. end;
  194. {$ENDIF}
  195. function TRxDBRichEdit.EditCanModify: Boolean;
  196. begin
  197.   FStateChanging := True;
  198.   try
  199.     Result := FDataLink.Editing;
  200.     if not Result and Assigned(FDataLink.Field) then
  201.     try
  202. {$IFDEF RX_D3}
  203.       if FDataLink.Field.IsBlob then
  204. {$ELSE}
  205.       if FDataLink.Field is TBlobField then
  206. {$ENDIF}
  207.         FDataSave := FDataLink.Field.AsString;
  208.       Result := FDataLink.Edit;
  209.     finally
  210.       FDataSave := '';
  211.     end;
  212.   finally
  213.     FStateChanging := False;
  214.   end;
  215. end;
  216. procedure TRxDBRichEdit.KeyDown(var Key: Word; Shift: TShiftState);
  217. begin
  218.   inherited KeyDown(Key, Shift);
  219.   if FMemoLoaded then begin
  220.     if (Key in [VK_DELETE, VK_BACK, VK_CLEAR]) or
  221.       ((Key = VK_INSERT) and (ssShift in Shift)) or
  222.       (((Key = Ord('V')) or (Key = Ord('X'))) and (ssCtrl in Shift)) then
  223.       EditCanModify;
  224.   end
  225.   else Key := 0;
  226. end;
  227. procedure TRxDBRichEdit.KeyPress(var Key: Char);
  228. begin
  229.   inherited KeyPress(Key);
  230.   if FMemoLoaded then begin
  231.     if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
  232.       not FDataLink.Field.IsValidChar(Key) then
  233.     begin
  234.       MessageBeep(0);
  235.       Key := #0;
  236.     end;
  237.     case Key of
  238.       ^H, ^I, ^J, ^M, ^V, ^X, #32..#255: EditCanModify;
  239.       #27: FDataLink.Reset;
  240.     end;
  241.   end
  242.   else begin
  243.     if Key = Chr(VK_RETURN) then LoadMemo;
  244.     if FMemoLoaded then Key := #0;
  245.   end;
  246. end;
  247. procedure TRxDBRichEdit.Change;
  248. begin
  249.   if FMemoLoaded then FDataLink.Modified;
  250.   FMemoLoaded := True;
  251.   inherited Change;
  252. end;
  253. function TRxDBRichEdit.GetDataSource: TDataSource;
  254. begin
  255.   Result := FDataLink.DataSource;
  256. end;
  257. procedure TRxDBRichEdit.SetDataSource(Value: TDataSource);
  258. begin
  259.   FDataLink.DataSource := Value;
  260.   if Value <> nil then Value.FreeNotification(Self);
  261. end;
  262. function TRxDBRichEdit.GetDataField: string;
  263. begin
  264.   Result := FDataLink.FieldName;
  265. end;
  266. procedure TRxDBRichEdit.SetDataField(const Value: string);
  267. begin
  268.   FDataLink.FieldName := Value;
  269. end;
  270. function TRxDBRichEdit.GetReadOnly: Boolean;
  271. begin
  272.   Result := FDataLink.ReadOnly;
  273. end;
  274. procedure TRxDBRichEdit.SetReadOnly(Value: Boolean);
  275. begin
  276.   FDataLink.ReadOnly := Value;
  277. end;
  278. function TRxDBRichEdit.GetField: TField;
  279. begin
  280.   Result := FDataLink.Field;
  281. end;
  282. procedure TRxDBRichEdit.LoadMemo;
  283. {$IFDEF RX_D3}
  284. begin
  285.   if FMemoLoaded or (FDataLink.Field = nil) or not
  286.     FDataLink.Field.IsBlob then Exit;
  287.   FUpdating := True;
  288.   try
  289.     try
  290.       Lines.Assign(FDataLink.Field);
  291.       FMemoLoaded := True;
  292.     except
  293.       on E: EOutOfResources do
  294.         Lines.Text := Format('(%s)', [E.Message]);
  295.     end;
  296.     EditingChange(Self);
  297.   finally
  298.     FUpdating := False;
  299.   end;
  300. {$ELSE}
  301. var
  302.   Stream: TBlobStream;
  303. begin
  304.   if FMemoLoaded or (FDataLink.Field = nil) or not
  305.     (FDataLink.Field is TBlobField) then Exit;
  306.   FUpdating := True;
  307.   try
  308.     Stream := TBlobStream.Create(TBlobField(FDataLink.Field), bmRead);
  309.     try
  310.       try
  311.         Lines.LoadFromStream(Stream);
  312.         FMemoLoaded := True;
  313.       except
  314.         on E: EOutOfResources do
  315.           Lines.Text := Format('(%s)', [E.Message]);
  316.       end;
  317.     finally
  318.       Stream.Free;
  319.     end;
  320.     EditingChange(Self);
  321.   finally
  322.     FUpdating := False;
  323.   end;
  324. {$ENDIF}
  325. end;
  326. procedure TRxDBRichEdit.DataChange(Sender: TObject);
  327. begin
  328.   if FDataLink.Field = nil then begin
  329.     if (csDesigning in ComponentState) then Text := Name
  330.     else Text := '';
  331.     FMemoLoaded := False;
  332.   end
  333. {$IFDEF RX_D3}
  334.   else if FDataLink.Field.IsBlob then begin
  335. {$ELSE}
  336.   else if FDataLink.Field is TBlobField then begin
  337. {$ENDIF}
  338.     if AutoDisplay or (FDataLink.Editing and FMemoLoaded) then
  339.     begin
  340.       { Check if the data has changed since we read it the first time }
  341.       if FStateChanging and (FDataSave <> '') and
  342.         (FDataSave = FDataLink.Field.AsString) then Exit;
  343.       FMemoLoaded := False;
  344.       LoadMemo;
  345.     end
  346.     else begin
  347.       Text := Format('(%s)', [FDataLink.Field.DisplayLabel]);
  348.       FMemoLoaded := False;
  349.     end;
  350.   end
  351.   else if FDataLink.CanModify then begin
  352.     if not FStateChanging then begin
  353.       inherited SetPlainText(True);
  354.       if FFocused then Text := FDataLink.Field.Text
  355.       else Text := FDataLink.Field.DisplayText;
  356.       FMemoLoaded := True;
  357.     end;
  358.   end
  359.   else begin
  360.     inherited SetPlainText(True);
  361.     Text := FDataLink.Field.DisplayText;
  362.     FMemoLoaded := True;
  363.   end;
  364.   if HandleAllocated then
  365.     RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ERASE or RDW_FRAME);
  366. end;
  367. procedure TRxDBRichEdit.EditingChange(Sender: TObject);
  368. begin
  369.   inherited ReadOnly := not (FDataLink.Editing and FMemoLoaded);
  370. end;
  371. procedure TRxDBRichEdit.UpdateData(Sender: TObject);
  372. {$IFDEF RX_D3}
  373. begin
  374.   if (FDataLink.Field <> nil) then begin
  375.     if FDataLink.Field.IsBlob then FDataLink.Field.Assign(Lines)
  376.     else FDataLink.Field.AsString := Text;
  377.   end;
  378. {$ELSE}
  379. var
  380.   Stream: TBlobStream;
  381. begin
  382.   if FDataLink.Field is TBlobField then begin
  383.     Stream := TBlobStream.Create(TBlobField(FDataLink.Field), bmWrite);
  384.     try
  385.       if Lines.Count > 0 then Lines.SaveToStream(Stream);
  386.     finally
  387.       Stream.Free;
  388.     end;
  389.   end
  390.   else FDataLink.Field.AsString := Text;
  391. {$ENDIF}
  392. end;
  393. procedure TRxDBRichEdit.SetFocused(Value: Boolean);
  394. begin
  395.   if FFocused <> Value then begin
  396.     FFocused := Value;
  397.     if not Assigned(FDataLink.Field) or not
  398. {$IFDEF RX_D3}
  399.       FDataLink.Field.IsBlob then
  400. {$ELSE}
  401.       (FDataLink.Field is TBlobField) then
  402. {$ENDIF}
  403.       FDataLink.Reset;
  404.   end;
  405. end;
  406. procedure TRxDBRichEdit.CMEnter(var Message: TCMEnter);
  407. begin
  408.   SetFocused(True);
  409.   inherited;
  410. {$IFDEF RX_D3}
  411.   if SysLocale.FarEast and FDataLink.CanModify then
  412.     inherited ReadOnly := False;
  413. {$ENDIF RX_D3}
  414. end;
  415. procedure TRxDBRichEdit.CMExit(var Message: TCMExit);
  416. begin
  417.   try
  418.     FDataLink.UpdateRecord;
  419.   except
  420.     if CanFocus then SetFocus;
  421.     raise;
  422.   end;
  423.   SetFocused(False);
  424.   inherited;
  425. end;
  426. procedure TRxDBRichEdit.SetAutoDisplay(Value: Boolean);
  427. begin
  428.   if Value <> FAutoDisplay then begin
  429.     FAutoDisplay := Value;
  430.     if FAutoDisplay then LoadMemo;
  431.   end;
  432. end;
  433. procedure TRxDBRichEdit.SetPlainText(Value: Boolean);
  434. begin
  435.   if PlainText <> Value then begin
  436.     inherited SetPlainText(Value);
  437.     if FMemoLoaded then FDataLink.Reset;
  438.   end;
  439. end;
  440. procedure TRxDBRichEdit.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  441. begin
  442.   if not FMemoLoaded then LoadMemo
  443.   else inherited;
  444. end;
  445. procedure TRxDBRichEdit.WMCut(var Message: TMessage);
  446. begin
  447.   EditCanModify;
  448.   inherited;
  449. end;
  450. procedure TRxDBRichEdit.WMPaste(var Message: TMessage);
  451. begin
  452.   EditCanModify;
  453.   inherited;
  454. end;
  455. procedure TRxDBRichEdit.CMGetDataLink(var Message: TMessage);
  456. begin
  457.   Message.Result := Longint(FDataLink);
  458. end;
  459. procedure TRxDBRichEdit.UpdateMemo;
  460. begin
  461.   if FDataLink.Editing and FMemoLoaded then UpdateData(Self);
  462. end;
  463. {$IFDEF RX_D4}
  464. function TRxDBRichEdit.ExecuteAction(Action: TBasicAction): Boolean;
  465. begin
  466.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  467.     FDataLink.ExecuteAction(Action);
  468. end;
  469. function TRxDBRichEdit.UpdateAction(Action: TBasicAction): Boolean;
  470. begin
  471.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  472.     FDataLink.UpdateAction(Action);
  473. end;
  474. {$ENDIF}
  475. procedure TRxDBRichEdit.EMSetCharFormat(var Message: TMessage);
  476. begin
  477.   if FMemoLoaded then begin
  478.     if not FUpdating then begin
  479.       if EditCanModify then Change;
  480.     end;
  481.   end;
  482.   inherited;
  483. end;
  484. procedure TRxDBRichEdit.EMSetParaFormat(var Message: TMessage);
  485. begin
  486.   if FMemoLoaded then begin
  487.     if not FUpdating then begin
  488.       if EditCanModify then Change;
  489.     end;
  490.   end;
  491.   inherited;
  492. end;
  493. {$ENDIF WIN32}
  494. end.