可以用WINDOWS带的画图软件,或photoshop吧!

解决方案 »

  1.   

    {
        Copyright (C) 2001,  Windoze, [email protected]    This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU Library General Public License as published
        by the Free Software Foundation; either version 2 of the License, or
        (at your option) any later version.    This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Library Public License for more details.    You should have received a copy of the GNU Library General Public License
        along with this program; if not, write to the Free Software Foundation,
        Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    }{
        RICHOLE.PAS
     
        Purpose:
            OLE Extensions to the Rich Text Editor
    }
     
    {
        Translated CPP header file, this file was NOT well-formed for C++ Builder.
        Don't use it under such environment unless you modified it properly.
    }unit RichOle;interfaceuses
      Windows, Messages, SysUtils, Classes, RichEdit, ActiveX;const
    // IID
      IID_IRichEditOle : TGUID = '{00020D00-0000-0000-C000-000000000046}';
      IID_IRichEditOleCallback : TGUID = '{00020D03-0000-0000-C000-000000000046}';// Flags to specify which interfaces should be returned in the structure above
      REO_GETOBJ_NO_INTERFACES = $00000000;
      REO_GETOBJ_POLEOBJ = $00000001;
      REO_GETOBJ_PSTG = $00000002;
      REO_GETOBJ_POLESITE = $00000004;
      REO_GETOBJ_ALL_INTERFACES = $00000007;// Place object at selection
      REO_CP_SELECTION  = -1;// Use character position to specify object instead of index
      REO_IOB_SELECTION  = -1;
      REO_IOB_USE_CP = -2;// Object flags
      REO_NULL = $00000000; // No flags
      REO_READWRITEMASK = $0000003F; // Mask out RO bits
      REO_DONTNEEDPALETTE = $00000020; // Object doesn't need palette
      REO_BLANK = $00000010; // Object is blank
      REO_DYNAMICSIZE = $00000008; // Object defines size always
      REO_INVERTEDSELECT = $00000004; // Object drawn all inverted if sel
      REO_BELOWBASELINE = $00000002; // Object sits below the baseline
      REO_RESIZABLE = $00000001; // Object may be resized
      REO_LINK = $80000000; // Object is a link (RO)
      REO_STATIC = $40000000; // Object is static (RO)
      REO_SELECTED = $08000000; // Object selected (RO)
      REO_OPEN = $04000000; // Object open in its server (RO)
      REO_INPLACEACTIVE = $02000000; // Object in place active (RO)
      REO_HILITED = $01000000; // Object is to be hilited (RO)
      REO_LINKAVAILABLE = $00800000; // Link believed available (RO)
      REO_GETMETAFILE = $00400000; // Object requires metafile (RO)// flags for IRichEditOle::GetClipboardData(),
    // IRichEditOleCallback::GetClipboardData() and
    // IRichEditOleCallback::QueryAcceptData()
      RECO_PASTE = $00000000; // paste from clipboard
      RECO_DROP = $00000001; // drop
      RECO_COPY = $00000002; // copy to the clipboard
      RECO_CUT = $00000003; // cut to the clipboard
      RECO_DRAG = $00000004; // dragtype
      LONG=Integer;// Structure passed to GetObject and InsertObject
      _reobject = packed record
    cbStruct : DWORD;
    cp : LONG;
    clsid : TGUID;
    poleobject : IOleObject;
    pstg : IStorage;
    polesite : IOleClientSite;
    sizel : SIZE;
    dvaspect : DWORD;
    dwFlags : DWORD;
    dwUser : DWORD;
      end;  REOBJECT=_reobject;
      PREOBJECT=^REOBJECT;
      LPREOBJECT=PREOBJECT;
      IRichEditOle = interface(IUnknown)
      ['{00020D00-0000-0000-C000-000000000046}']
    function GetClientSite(out lplpolesite : IOleClientSite) : HRESULT; stdcall;
    function GetObjectCount : LONG; stdcall;
    function GetLinkCount : LONG; stdcall;
    function GetObject(iob : LONG; var lpreobject : REOBJECT; dwFlags : DWORD) : HRESULT; stdcall;
    function InsertObject(var lpreobject : REOBJECT) : HRESULT; stdcall;
    function ConvertObject(iob : LONG; rclsidNew : TGUID; lpsreUserTypeNew : LPCSTR) : HRESULT; stdcall;
    function ActivateAs(rclsid : TGUID; rclsidAs : TGUID) : HRESULT; stdcall;
    function SetHostNames(lpstrContainerApp : LPCSTR; lpstrContainerObj : LPCSTR) : HRESULT; stdcall;
    function SetLinkAvailable(iob : LONG; fAvailable : BOOL) : HRESULT; stdcall;
    function SetDvaspect(iob : LONG; dvaspect : DWORD) : HRESULT; stdcall;
    function HandsOffStorage(iob : LONG) : HRESULT; stdcall;
    function SaveCompleted(iob : LONG; lpstg : IStorage) : HRESULT; stdcall;
    function InPlaveDeactivate : HRESULT; stdcall;
    function ContextSensitiveHelp(fEnterMode : BOOL) : HRESULT; stdcall;
    function GetClipboardData(var lpchrg : CHARRANGE; reco : DWORD; out lplpdataobj : IDataObject) : HRESULT; stdcall;
    function ImportDataObject(out lpdataobj : IDataObject; cf : TClipFormat; hMetaPict : HGLOBAL) : HRESULT; stdcall;
      end;  IRichEditOleCallback = interface(IUnknown)
      ['{00020D03-0000-0000-C000-000000000046}']
    function GetNewStorage(out lplpstg : IStorage) : HRESULT; stdcall;
    function GetInPlaceContext(out lplpFrame : IOleInplaceFrame;
     out lplpDoc : IOleInplaceUIWindow;
     var lpFrameInfo : OLEINPLACEFRAMEINFO) : HRESULT; stdcall;
    function ShowContainerUI(fShow : BOOL) : HRESULT; stdcall;
    function QueryInsertObject(var lpclsid : TGUID; lpstg : IStorage; cp : LONG) : HRESULT; stdcall;
    function DeleteObject(lpoleobj : IOleObject) : HRESULT; stdcall;
    function QueryAcceptData(lpoleobj : IOleObject;
     var lpcfFormat : TClipFormat;
     reco : DWORD;
     fReally : BOOL;
     hMetaPict : HGLOBAL) : HRESULT; stdcall;
    function ContextSensitiveHelp(fEnterMode : BOOL) : HRESULT; stdcall;
    function GetClipboardData(var lpchrg : CHARRANGE; reco : DWORD;
    out lplpdataobj : IDataObject) : HRESULT; stdcall;
    function GetDragDropEffect(fDrag : BOOL; grfKeyState : DWORD; var pdwEffect : DWORD) : HRESULT; stdcall;
    function GetContextMenu(seltype : WORD; lpoleobj : IOleObject; var lpchrg : CHARRANGE; var lphmenu : HMENU) : HRESULT; stdcall;
      end;  PRICHEDITOLECALLBACK = ^IRichEditOleCallback;
      LPRICHEDITOLECALLBACK = PRICHEDITOLECALLBACK;implementationend.
      

  2.   

    {
        Copyright (C) 2001,  Windoze, [email protected]    This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU Library General Public License as published
        by the Free Software Foundation; either version 2 of the License, or
        (at your option) any later version.    This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Library Public License for more details.    You should have received a copy of the GNU Library General Public License
        along with this program; if not, write to the Free Software Foundation,
        Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    }{
        RICHEDITOR2EDITOR.PAS
     
        Purpose:
            Component editor for TRichEdit2
    }
     
    unit RichEdit2Editor;interface{
      If you have Win2KDlg components, you can enable this option.
      Ok, forget it :)
    }
    {.$DEFINE USES_WIN2KDLG}uses
    Windows, Sysutils, Messages, ComObj, Classes, Controls, ActiveX, ComCtrls,
    RichEdit2, RichOle, dsgnintf, shellapi, Dialogs
    {$IFDEF USES_WIN2KDLG}
    ,Win2KDlg
    {$ENDIF}
    ;type
    TRichEdit2Editor = class(TComponentEditor)
    function GetVerbCount : Integer; override;
    function GetVerb(Index : Integer) : string; override;
    procedure ExecuteVerb(Index : Integer); override;
    procedure Edit; override; procedure EditRichEditContent(re : TRichEdit2);
    procedure LoadRichTextFile(re : TRichEdit2);
    procedure Clear(re : TRichEdit2);
    end; procedure Register;implementationfunction TRichEdit2Editor.GetVerbCount : Integer;
    begin
    Result := (inherited GetVerbCount) + 3;
    end;function TRichEdit2Editor.GetVerb(Index : Integer) : string;
    begin
    if Index < (inherited GetVerbCount) then
    Result := inherited GetVerb(Index)
    else if Index = inherited GetVerbCount then
    Result := 'Edit...'
    else if Index = (inherited GetVerbCount)+1 then
    Result := 'Load File'
    else if Index = (inherited GetVerbCount)+2 then
    Result := 'Clear';
    end;procedure TRichEdit2Editor.ExecuteVerb(Index : Integer);
    begin
    if Index < inherited GetVerbCount then
    inherited
    else if Index = inherited GetVerbCount then
    EditRichEditContent(Component as TRichEdit2)
    else if Index = (inherited GetVerbCount)+1 then
    LoadRichTextFile(Component as TRichEdit2)
    else if Index = (inherited GetVerbCount)+2 then
    Clear(Component as TRichEdit2)
    end;procedure TRichEdit2Editor.Edit;
    begin
    EditRichEditContent(Component as TRichEdit2);
    end;{
    This is a quick-and-dirty content editor, simply save to a temporary file
    and run associated program to edit saved file, then reload the file into
    control.
    }
    procedure TRichEdit2Editor.EditRichEditContent(re : TRichEdit2); function MakeTempFileName : string;
    var
    pszTempDir : PChar;
    pszFileName : PChar;
    begin
    pszTempDir := AllocMem(MAX_PATH);
    pszFileName := AllocMem(MAX_PATH);
    GetTempPath(MAX_PATH, pszTempDIr);
    // I've to create a new file to get a temporary file name :(
    GetTempFileName(pszTempDir, 'tnt', 0, pszFileName);
    Result := pszFileName;
    // Delete created file, we need only a file name
    DeleteFile(Result);
    FreeMem(pszTempDir);
    FreeMem(pszFileName);
    end;
    var
    fn : string;
    fs : TFileStream;
    se : SHELLEXECUTEINFO;
    begin
    if re.PlainText then
    fn := MakeTempFileName + '.txt'
    else
    fn := MakeTempFileName + '.rtf';
    fs := TFileStream.Create(fn, fmCreate);
    re.SaveToStream(fs, re.PlainText);
    fs.Free;
    se.cbSize := SizeOf(se);
    se.fMask := SEE_MASK_NOCLOSEPROCESS;
    se.Wnd := re.Handle;
    se.lpVerb := nil;
    se.lpFile := PChar(fn);
    se.lpParameters := nil;
    se.lpDirectory := '.';
    se.nShow := SW_SHOW;
    ShellExecuteEx(@se);
    // Wait until program closed
    WaitForSingleObject(se.hProcess, INFINITE);
    fs := TFileStream.Create(fn, fmOpenRead);
    re.LoadFromStream(fs, re.PlainText);
    fs.Free;
    DeleteFile(fn);
    // Since the 'Data' property is NOT a real property, we've to
    // call IFormDesigner.Modified manually
    GetDesigner.Modified;
    end;procedure TRichEdit2Editor.LoadRichTextFile(re : TRichEdit2);
    var
    {$IFDEF USES_WIN2KDLG}
    dlg : TOpenDialogEx;
    {$ELSE}
    dlg : TOpenDialog;
    {$ENDIF}
    fs : TFileStream;
    begin
    {$IFDEF USES_WIN2KDLG}
    dlg := TOpenDialogEx.Create(re.Owner);
    dlg.ShowPlacesBar := True;
    {$ELSE}
    dlg := TOpenDialog.Create(re.Owner);
    {$ENDIF}
    if re.PlainText then
    dlg.Filter := 'Text Files(*.txt)|*.TXT|All Files(*.*)|*.*|'
    else
    dlg.Filter := 'RTF Files(*.rtf)|*.RTF|All Files(*.*)|*.*|';
    dlg.FilterIndex := 1;
    dlg.Options := [ofHideReadOnly,ofShowHelp,ofPathMustExist,ofFileMustExist,ofEnableSizing];
    if dlg.Execute then
    begin
    fs := TFileStream.Create(dlg.FileName, fmOpenRead);
    re.LoadFromStream(fs, re.PlainText);
    fs.Free;
    GetDesigner.Modified;
    end;
    dlg.Free;
    end;procedure TRichEdit2Editor.Clear(re : TRichEdit2);
    begin
    re.Clear;
    end;procedure Register;
    begin
    RegisterComponentEditor(TCustomRichEdit2, TRichEdit2Editor);
    end;end.
      

  3.   

    unit RichEdit2;interface{
    Remove prior dot to enable OLE Inplace activation Unfortunately, current implementation of inplace-activation still buggy,
    sometimes inserted object cannot update properly, so you'd better don't
    enable this feature...
    }
    {.$DEFINE USES_IPACTIVATE}{
    Remove prior dot to add a TextDocument property, with this you can
    access an ITOMDocument interface owned by the richedit control.
    You must generate tom_TLB.pas/dcr from you riched20.dll, I don't
    supply this file to avoid version conflict.
    }
    {.$DEFINE USES_TOM}uses
    Windows, Messages, ComObj, Classes, Controls, ActiveX, ComCtrls, ComStrs,
    RichEdit, RichOle, Graphics, SysUtils, forms
    {$IFDEF USES_IPACTIVATE}
    , olectnrs
    {$ENDIF}{$IFDEF USES_TOM}
    , tom_TLB
    {$ENDIF}
    ;const
    EM_GETZOOM = (WM_USER + 224);
    EM_SETZOOM = (WM_USER + 225);type
    TRichEditLinkNotify = procedure(Sender: TObject;
    StartPos, EndPos: Integer; NotifyMessage : Longint; var Handled: Boolean) of object; TRichEditMargin = class(TPersistent)
    protected
    FRECtrl : TCustomRichEdit;
    FWidth : Integer;
    FUseFontInfo : Boolean;
    FDirect : Boolean; // True = Left, False = Right
    FPlainTextMode : Boolean;
    procedure SetWidth(AWidth : Integer);
    procedure SetUseFontInfo(AUseFontInfo : Boolean);
    procedure SetMargin;
    property UseFontInfo : Boolean read FUseFontInfo write SetUseFontInfo; public
    constructor Create(AOwner : TComponent); virtual;
    procedure Assign(Source: TPersistent); override; published
    property Width : Integer read FWidth write SetWidth;
    end; TCustomRichEdit2 = class(TCustomRichEdit, IRichEditOleCallback)
    private
    REObject : IRichEditOle;
    FLeftMargin, FRightMargin : TRichEditMargin;
    FLinkNotify : TRichEditLinkNotify;
    FPlainTextMode : Boolean;
    FLines : TStrings;
    ReloadStream : TMemoryStream;
    {$IFDEF USES_TOM}
    TOMDocument : ITextDocument;
    {$ENDIF}
    protected
    // Interface methods
    // *** IRichEditOleCallback methods ***
    function GetNewStorage(out lplpstg : IStorage) : HRESULT; stdcall;
    function GetInPlaceContext(out lplpFrame : IOleInplaceFrame;
     out lplpDoc : IOleInplaceUIWindow;
     var lpFrameInfo : OLEINPLACEFRAMEINFO) : HRESULT; stdcall;
    function ShowContainerUI(fShow : BOOL) : HRESULT; stdcall;
    function QueryInsertObject(var lpclsid : TGUID; lpstg : IStorage; cp : LONG) : HRESULT; stdcall;
    function DeleteObject(lpoleobj : IOleObject) : HRESULT; stdcall;
    function QueryAcceptData(lpoleobj : IOleObject;
     var lpcfFormat : TClipFormat;
     reco : DWORD;
     fReally : BOOL;
     hMetaPict : HGLOBAL) : HRESULT; stdcall;
    function ContextSensitiveHelp(fEnterMode : BOOL) : HRESULT; stdcall;
    function GetClipboardData(var lpchrg : CHARRANGE; reco : DWORD;
    out lplpdataobj : IDataObject) : HRESULT; stdcall;
    function GetDragDropEffect(fDrag : BOOL; grfKeyState : DWORD; var pdwEffect : DWORD) : HRESULT; stdcall;
    function GetContextMenu(seltype : WORD; lpoleobj : IOleObject; var lpchrg : CHARRANGE; var lphmenu : HMENU) : HRESULT; stdcall; // Message functions
    procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
    function SaveClipboard(NumObj, NumChars: Integer): Boolean;
    function ProtectChange(StartPos, EndPos: Integer): Boolean;
    function LinkNotify(StartPos, EndPos: Integer; NotifyMessage : Longint): Boolean; // Virtual functions
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWnd; override; function ReadFromStream(Stream : TStream; var Buffer; var Count : Longint) : Longint; virtual;
    function WriteToStream(Stream : TStream; const Buffer; var Count : Longint) : Longint; virtual;
    procedure DefineProperties(Filer: TFiler); override; procedure ReadData(Stream : TStream);
    procedure WriteData(Stream : TStream); // Properties;
    function GetAutoURLDetect : Boolean;
    procedure SetAutoURLDetect(FActive : Boolean);
    function GetCanRedo : Boolean;
    procedure SetSelectionVisible(FVisible : Boolean);
    function GetZoomRatio : Real;
    procedure SetZoomRatio(AZoomRatio : Real);
    procedure SetPlainTextMode(ATextMode : Boolean);
    procedure SetLines(Value: TStrings);{$IFDEF USES_TOM}
    function GetTOMDocument : ITextDocument;
    function UndoEx(Count : Longint) : Longint;
    function RedoEx(Count : Longint) : Longint;
    {$ENDIF}
    public
    constructor Create(AOwner : TComponent); override;
    procedure DestroyWnd; override;
    destructor Destroy; override;
    // Methods
    procedure Clear; override;
    procedure LoadFromStream(Stream : TStream; FromText : Boolean=False; Selection : Boolean=False; Unicode : Boolean=False);
    procedure SaveToStream(Stream : TStream; ToText : Boolean=False; Selection : Boolean=False; Unicode : Boolean=False);
    procedure Redo;
    function CanPaste(ClipboardFormat : WORD=0) : Boolean;
    // Properties
    property CanRedo : Boolean read GetCanRedo;
    property SelectionVisible : Boolean write SetSelectionVisible;
    property AutoURLDetect : Boolean read GetAutoURLDetect write SetAutoURLDetect;
    property LeftMargin : TRichEditMargin read FLeftMargin write FLeftMargin;
    property RightMargin : TRichEditMargin read FRightMargin write FRightMargin;
    property ZoomRatio : Real read GetZoomRatio write SetZoomRatio;
    {$IFDEF USES_TOM}
    property TextDocument : ITextDocument read GetTOMDocument;
    {$ENDIF} // Changed, not fully implemented, yet
    property PlainText : Boolean read FPlainTextMode write SetPlainTextMode; // Events
    property OnLinkNotify : TRichEditLinkNotify read FLinkNotify write FLinkNotify;
    property Lines read FLines write SetLines;
    published
    end; TRichEdit2 = class(TCustomRichEdit2)
    published
    property Align;
    property Alignment;
    property Anchors;
    property AutoURLDetect;
    property BiDiMode;
    property BorderStyle;
    property BorderWidth;
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property Font;
    property HideSelection;
    property HideScrollBars;
    property ImeMode;
    property ImeName;
    property Constraints;
    property Lines;
    property MaxLength;
    property ParentBiDiMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PlainText;
    property PopupMenu;
    property ReadOnly;
    property ScrollBars;
    property ShowHint;
    property TabOrder;
    property TabStop default True;
        property Visible;
        property WantTabs;
        property WantReturns;
    property WordWrap;
    property LeftMargin;
    property RightMargin;
    property ZoomRatio;
        property OnChange;
    property OnContextPopup;
        property OnDragDrop;
        property OnDragOver;
        property OnEndDock;
    property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnKeyDown;
    property OnKeyPress;
        property OnKeyUp;
    property OnMouseDown;
        property OnMouseMove;
    property OnMouseUp;
        property OnMouseWheel;
        property OnMouseWheelDown;
        property OnMouseWheelUp;
        property OnProtectChange;
        property OnResizeRequest;
        property OnSaveClipboard;
    property OnSelectionChange;
    property OnStartDock;
    property OnStartDrag;
    property OnLinkNotify;
    end;{
    Need a TDBRichEdit2? Do it youself. :)
    Maybe you've to use a BLOB field to store data...
    }
      

  4.   

    Is That really OK?! TKS
      

  5.   

    procedure Register;implementationtype
    // Copy from VCL source and remove some members
    TRichEdit2Strings = class(TStrings)
    private
    RichEdit: TCustomRichEdit2;
    procedure EnableChange(const Value: Boolean);
    protected
    function Get(Index: Integer): string; override;
    function GetCount: Integer; override;
    procedure Put(Index: Integer; const S: string); override;
    procedure SetUpdateState(Updating: Boolean); override;
    procedure SetTextStr(const Value: string); override;
    public
    procedure Clear; override;
    procedure AddStrings(Strings: TStrings); override;
    procedure Delete(Index: Integer); override;
    procedure Insert(Index: Integer; const S: string); override;
    end;procedure TRichEdit2Strings.AddStrings(Strings: TStrings);
    var
    SelChange: TNotifyEvent;
    begin
    SelChange := RichEdit.OnSelectionChange;
    RichEdit.OnSelectionChange := nil;
    try
    inherited AddStrings(Strings);
    finally
    RichEdit.OnSelectionChange := SelChange;
    end;
    end;function TRichEdit2Strings.GetCount: Integer;
    begin
    Result := SendMessage(RichEdit.Handle, EM_GETLINECOUNT, 0, 0);
    if SendMessage(RichEdit.Handle, EM_LINELENGTH, SendMessage(RichEdit.Handle,
    EM_LINEINDEX, Result - 1, 0), 0) = 0 then Dec(Result);
    end;function TRichEdit2Strings.Get(Index: Integer): string;
    var
    Text: array[0..4095] of Char;
    L: Integer;
    begin
    Word((@Text)^) := SizeOf(Text);
    L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, Longint(@Text));
    if (Text[L - 2] = #13) and (Text[L - 1] = #10) then Dec(L, 2);
    SetString(Result, Text, L);
    end;procedure TRichEdit2Strings.Put(Index: Integer; const S: string);
    var
    Selection: TCharRange;
    begin
    if Index >= 0 then
    begin
    Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
    if Selection.cpMin <> -1 then
    begin
    Selection.cpMax := Selection.cpMin +
    SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
    SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
    SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, Longint(PChar(S)));
    end;
    end;
    end;procedure TRichEdit2Strings.Insert(Index: Integer; const S: string);
    var
    L: Integer;
    Selection: TCharRange;
    Fmt: PChar;
    Str: string;
    begin
    if Index >= 0 then
    begin
    Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
    if Selection.cpMin >= 0 then Fmt := '%s'#13#10
    else begin
    Selection.cpMin :=
    SendMessage(RichEdit.Handle, EM_LINEINDEX, Index - 1, 0);
    if Selection.cpMin < 0 then Exit;
    L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
    if L = 0 then Exit;
    Inc(Selection.cpMin, L);
    Fmt := #13#10'%s';
    end;
    Selection.cpMax := Selection.cpMin;
    SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
    Str := Format(Fmt, [S]);
    SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, LongInt(PChar(Str)));{
    Removed
    if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
    raise EOutOfResources.Create(sRichEditInsertError);
    }
    end;
    end;procedure TRichEdit2Strings.Delete(Index: Integer);
    const
    Empty: PChar = '';
    var
    Selection: TCharRange;
    begin
    if Index < 0 then Exit;
    Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
    if Selection.cpMin <> -1 then
    begin
    Selection.cpMax := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index + 1, 0);
    if Selection.cpMax = -1 then
    Selection.cpMax := Selection.cpMin +
    SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
    SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
    SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, Longint(Empty));
    end;
    end;procedure TRichEdit2Strings.Clear;
    begin
    RichEdit.Clear;
    end;procedure TRichEdit2Strings.SetUpdateState(Updating: Boolean);
    begin
    if RichEdit.Showing then
    SendMessage(RichEdit.Handle, WM_SETREDRAW, Ord(not Updating), 0);
    if not Updating then begin
    RichEdit.Refresh;
    RichEdit.Perform(CM_TEXTCHANGED, 0, 0);
    end;
    end;procedure TRichEdit2Strings.EnableChange(const Value: Boolean);
    var
    EventMask: Longint;
    begin
    with RichEdit do
    begin
    if Value then
    EventMask := SendMessage(Handle, EM_GETEVENTMASK, 0, 0) or ENM_CHANGE
    else
    EventMask := SendMessage(Handle, EM_GETEVENTMASK, 0, 0) and not ENM_CHANGE;
    SendMessage(Handle, EM_SETEVENTMASK, 0, EventMask);
    end;
    end;procedure TRichEdit2Strings.SetTextStr(const Value: string);
    begin
    EnableChange(False);
    try
    inherited SetTextStr(Value);
    finally
    EnableChange(True);
    end;
    end;{
    procedure TRichEdit2Strings.LoadFromStream(Stream: TStream);
    begin
    raise Exception.Create('Not implemented function');
    end;procedure TRichEdit2Strings.SaveToStream(Stream: TStream);
    begin
    raise Exception.Create('Not implemented function');
    end;procedure TRichEdit2Strings.LoadFromFile(const FileName: string);
    begin
    raise Exception.Create('Not implemented function');
    end;procedure TRichEdit2Strings.SaveToFile(const FileName: string);
    begin
    raise Exception.Create('Not implemented function');
    end;
    }constructor TRichEditMargin.Create(AOwner : TComponent);
    begin
    FWidth := 4;
    FUseFontInfo := False;
    end;procedure TRichEditMargin.Assign(Source : TPersistent);
    begin
    FWidth := (Source as TRichEditMargin).FWidth;
    FUseFontInfo := (Source as TRichEditMargin).FUseFontInfo;
    end;procedure TRichEditMargin.SetMargin;
    var
    wParam : DWORD;
    lParam : DWORD;
    begin
    if FDirect then
    begin
    // Left margin
    wParam := EC_LEFTMARGIN;
    lParam := FWidth;
    if FUseFontInfo then
    begin
    wParam := wParam or EC_USEFONTINFO;
    lParam := EC_USEFONTINFO;
    end;
    end
    else
    begin
    // Right margin
    wParam := EC_RIGHTMARGIN;
    lParam := FWidth shl 16;
    if FUseFontInfo then
    begin
    wParam := wParam or EC_USEFONTINFO;
    lParam := $FFFF0000;
    end;
    end;
    SendMessage(FRECtrl.Handle, EM_SETMARGINS, wParam, lParam);
    end;procedure TRichEditMargin.SetWidth(AWidth : Integer);
    begin
    FWidth := AWidth;
    SetMargin;
    end;procedure TRichEditMargin.SetUseFontInfo(AUseFontInfo : Boolean);
    begin
    FUseFontInfo := AUseFontInfo;
    SetMargin;
    end;constructor TCustomRichEdit2.Create(AOwner : TComponent);
    begin
    inherited;
    FPlainTextMode := False;
    LeftMargin := TRichEditMargin.Create(Self);
    LeftMargin.FRECtrl := Self;
    LeftMargin.FDirect := True;
    RightMargin := TRichEditMargin.Create(Self);
    RightMargin.FRECtrl := Self;
    RightMargin.FDirect := False;
    FLines := TRichEdit2Strings.Create;
    TRichEdit2Strings(FLines).RichEdit := Self;
    end;
      

  6.   


    destructor TCustomRichEdit2.Destroy;
    begin
    LeftMargin.Free;
    RightMargin.Free;
    inherited;
    end;procedure TCustomRichEdit2.CreateParams(var Params: TCreateParams);
    begin
    inherited;
    CreateSubClass(Params, 'RICHEDIT20A');
    with Params do
    begin
    WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
    end;
    end;procedure TCustomRichEdit2.CreateWnd;
    var
    pI : IRichEditOleCallback;
    begin
    inherited; SendMessage(Handle, WM_SETFONT, Font.Handle, 0); pI := Self;
    SendMessage(Handle, EM_SETOLECALLBACK, 0, Integer(Pointer(pI)));
    SendMessage(Handle, EM_SETEVENTMASK, 0,
    ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or
    ENM_PROTECTED or ENM_LINK);
    LeftMargin.SetMargin;
    RightMargin.SetMargin; // Some properties' changing will re-create the window, to keep the content
    // we have to save and reload. // Reload data if needed
    if ReloadStream <> nil then
    begin
    ReloadStream.Position := 0;
    LoadFromStream(ReloadStream);
    ReloadStream.Free;
    ReloadStream := nil;
    end;end;procedure TCustomRichEdit2.DestroyWnd;
    begin
    // Release interfaces
    if REObject<>nil then
    begin
    REObject := nil;
    end;
    {$IFDEF USES_TOM}
    if TOMDocument<>nil then
    begin
    TOMDocument := nil;
    end;
    {$ENDIF} // Tempororally save data if needed
    if not (csDestroying in ComponentState) then
    begin
    ReloadStream := TMemoryStream.Create;
    SaveToStream(ReloadStream);
    end; inherited;
    end;type
    PENLink = ^TENLink;procedure TCustomRichEdit2.DefineProperties(Filer: TFiler);
    begin
    inherited DefineProperties(Filer);
    Filer.DefineBinaryProperty('Data', ReadData, WriteData, True);
    end;procedure TCustomRichEdit2.ReadData(Stream : TStream);
    var
    Size : Longint;
    TempStream : TMemoryStream;
    begin
    TempStream := TMemoryStream.Create;
    try
    Stream.ReadBuffer(Size, SizeOf(Size));
    if Size>0 then
    begin
    TempStream.CopyFrom(Stream, Size);
    TempStream.position:= 0;
    LoadFromStream(TempStream);
    end;
    finally
    TempStream.Free;
    end;
    end;procedure TCustomRichEdit2.WriteData(Stream : TStream);
    var
    Size : Longint;
    TempStream : TMemoryStream;
    begin
    TempStream := TMemoryStream.Create;
    try
    SaveToStream(TempStream);
    TempStream.position:= 0;
    Size:= TempStream.Size;
    Stream.WriteBuffer(Size, SizeOf(Size));
    if Size>0 then
    Stream.WriteBuffer(PChar(TempStream.Memory)^, Size);
    finally
    TempStream.free;
    end;
    end;// Copy from VCL, mostly
    procedure TCustomRichEdit2.CNNotify(var Message: TWMNotify);
    begin
    with Message do
    case NMHdr^.code of
    EN_SELCHANGE: SelectionChange;
    EN_REQUESTRESIZE: RequestSize(PReqSize(NMHdr)^.rc);
    EN_SAVECLIPBOARD:
    with PENSaveClipboard(NMHdr)^ do
    if not SaveClipboard(cObjectCount, cch) then Result := 1;
    EN_PROTECTED:
    with PENProtected(NMHdr)^.chrg do
    if not ProtectChange(cpMin, cpMax) then Result := 1;
    EN_LINK:
    with PENLink(NMHdr)^.chrg do
    if LinkNotify(cpMin, cpMax, PENLink(NMHdr)^.msg) then Message.Result := 1;
    end;
    end;// Copy from VCL
    function TCustomRichEdit2.SaveClipboard(NumObj, NumChars: Integer): Boolean;
    begin
    Result := True;
    if Assigned(OnSaveClipboard) then OnSaveClipboard(Self, NumObj, NumChars, Result);
    end;// Copy from VCL
    function TCustomRichEdit2.ProtectChange(StartPos, EndPos: Integer): Boolean;
    begin
    Result := False;
    if Assigned(OnProtectChange) then OnProtectChange(Self, StartPos, EndPos, Result);
    end;function TCustomRichEdit2.LinkNotify(StartPos, EndPos: Integer; NotifyMessage : Longint): Boolean;
    begin
    Result := False;
    if Assigned(OnLinkNotify) then OnLinkNotify(Self, StartPos, EndPos, NotifyMessage, Result);
    end;function TCustomRichEdit2.GetAutoURLDetect;
    begin
    Result := Perform(EM_GETAUTOURLDETECT, 0, 0)=1;
    end;procedure TCustomRichEdit2.SetAutoURLDetect(FActive : Boolean);
    begin
    SendMessage(Handle, EM_AUTOURLDETECT, Integer(FActive), 0);
    end;function TCustomRichEdit2.GetZoomRatio : Real;
    var
    numerator, denominator : WORD;
    begin
    SendMessage(Handle, EM_GETZOOM, Longint(@numerator), Longint(@denominator));
    if (denominator=0) or (numerator=0) then
    Result := 1
    else
    Result := numerator/denominator;
    end;procedure TCustomRichEdit2.SetZoomRatio(AZoomRatio : Real);
    var
    numerator, denominator : DWORD;
    begin
    denominator := 100;
    numerator := Round(AZoomRatio * 100);
    SendMessage(Handle, EM_SETZOOM, numerator, denominator);
    end;procedure TCustomRichEdit2.SetPlainTextMode(ATextMode : Boolean);
    var
    cf2 : CHARFORMAT2;
    begin
    cf2.cbSize := SizeOf(cf2);
    cf2.dwMask := CFM_BACKCOLOR or CFM_CHARSET or CFM_COLOR
    or CFM_FACE or CFM_SIZE or CFM_UNDERLINETYPE or CFM_WEIGHT;
    cf2.dwEffects := 0;
    cf2.yHeight := -(Font.Height) * 1440 div Font.PixelsPerInch;
    cf2.yOffset := 0;
    cf2.crTextColor := Font.Color;
    cf2.bCharSet := Font.Charset;
    case Font.Pitch of
    fpDefault:
    cf2.bPitchAndFamily := DEFAULT_PITCH;
    fpFixed:
    cf2.bPitchAndFamily := FIXED_PITCH;
    fpVariable:
    cf2.bPitchAndFamily := VARIABLE_PITCH;
    end;
    StrLCopy(cf2.szFaceName, PChar(Font.Name), 31);
    if fsBold in Font.Style then
    cf2.wWeight := FW_BOLD
    else
    cf2.wWeight := FW_NORMAL;
    if fsUnderLine in Font.Style then
    cf2.bUnderlineType := CFU_UNDERLINE
    else
    cf2.bUnderlineType := CFU_UNDERLINENONE;
    cf2.crBackColor := ColorToRGB(Color);
    SendMessage(Handle, EM_SETCHARFORMAT, SCF_ALL, Integer(@cf2));
    FPlainTextMode := ATextMode;
    end;{$IFDEF USES_TOM}
    procedure TCustomRichEdit2.Clear;
    begin
    TextDocument.New;
    end;
    {$ELSE}
    type
    SETTEXTEX=packed record
    flags : DWORD;
    codepage : UINT;
    end;
    const
    ST_DEFAULT = 0;
    ST_KEEPUNDO = 1;
    ST_SELECTION = 2;
    EM_SETTEXTEX = (WM_USER + 97);
    procedure TCustomRichEdit2.Clear;
    var
    st : SETTEXTEX;
    ch : Char;
    begin
    st.flags := ST_DEFAULT;
    st.codepage := CP_ACP;
    ch := #0;
    SendMessage(Handle, EM_SETTEXTEX, Integer(@st), Integer(@ch));
    end;
    {$ENDIF}function TCustomRichEdit2.GetCanRedo : Boolean;
    begin
    Result := Perform(EM_CANREDO, 0, 0)<>0;
    end;procedure TCustomRichEdit2.Redo;
    begin
    SendMessage(Handle, EM_REDO, 0, 0);
    end;{$IFDEF USES_TOM}
    function TCustomRichEdit2.UndoEx(Count : Longint) : Longint;
    begin
    Result := TextDocument.Undo(Count);
    end;function TCustomRichEdit2.RedoEx(Count : Longint) : Longint;
    begin
    Result := TextDocument.Redo(Count);
    end;
    {$ENDIF}
      

  7.   


    function TCustomRichEdit2.CanPaste(ClipboardFormat : WORD=0) : Boolean;
    begin
    Result := SendMessage(Handle, EM_CANPASTE, ClipboardFormat, 0) <> 0;
    end;procedure TCustomRichEdit2.SetSelectionVisible(FVisible : Boolean);
    begin
    SendMessage(Handle, EM_HIDESELECTION, Longint(not FVisible), 0);
    end;{$IFDEF USES_TOM}
    function TCustomRichEdit2.GetTOMDocument : ITextDocument;
    begin
    if TOMDocument=nil then
    begin
    SendMessage(Handle, EM_GETOLEINTERFACE, 0, Longint(@REObject));
    TOMDocument := REObject as ITextDocument;
    end;
    Result := TOMDocument;
    end;
    {$ENDIF}procedure TCustomRichEdit2.SetLines(Value: TStrings);
    begin
    FLines.Assign(Value);
    end;// EM_STREAMIN/OUT implementations
    type
    TRichEditExCallback = record
    RichEditEx : TCustomRichEdit2;
    Stream : TStream;
    FRead : Boolean;
    end;
    PRichEditExCallback = ^TRichEditExCallback;function RichEditExStreamCallback(dwCookie: Longint; pbBuff: PByte;
    cb: Longint; var pcb: Longint): Longint; stdcall;
    var
    pCallBack : PRichEditExCallback;
    begin
    pCallBack := PRichEditExCallback(dwCookie);
    pcb := cb;
    if pCallBack^.FRead then
    Result := pCallBack^.RichEditEx.ReadFromStream(pCallBack^.Stream, pbBuff^, pcb)
    else
    Result := pCallBack^.RichEditEx.WriteToStream(pCallBack^.Stream, pbBuff^, pcb);
    end;procedure TCustomRichEdit2.LoadFromStream(Stream : TStream; FromText : Boolean=False; Selection : Boolean=False; Unicode : Boolean=False);
    var
    es : TEditStream;
    cb : TRichEditExCallback;
    Options : Longint;
    begin
    cb.Stream := Stream;
    cb.RichEditEx := Self;
    cb.FRead := True;
    es.dwCookie := Longint(@cb);
    es.dwError := 0;
    es.pfnCallback := RichEditExStreamCallback; // prepare options
    Options := 0;
    if FromText then
    Options := Options or SF_TEXT
    else
    Options := Options or SF_RTF;
    if Selection then
    Options := Options or SFF_SELECTION;
    if Unicode then
    Options := Options or SF_UNICODE; SendMessage(Handle, EM_STREAMIN, Options, Longint(@es)); // Check result
    if es.dwError<>0 then
    raise EReadError.CreateFmt('%s.LoadFromStream error, Error code is %d', [Name, es.dwError]);
    end;procedure TCustomRichEdit2.SaveToStream(Stream : TStream; ToText : Boolean=False; Selection : Boolean=False; Unicode : Boolean=False);
    var
    es : TEditStream;
    cb : TRichEditExCallback;
    Options : Longint;
    begin
    cb.Stream := Stream;
    cb.RichEditEx := Self;
    cb.FRead := False;
    es.dwCookie := Longint(@cb);
    es.dwError := 0;
    es.pfnCallback := RichEditExStreamCallback;
    // prepare options
    Options := 0;
    if ToText then
    Options := Options or SF_TEXT
    else
    Options := Options or SF_RTF;
    if Selection then
    Options := Options or SFF_SELECTION;
    if Unicode then
    Options := Options or SF_UNICODE; SendMessage(Handle, EM_STREAMOUT, Options, Longint(@es)); // Check result
    if es.dwError<>0 then
    raise EReadError.CreateFmt('%s.SaveToStream error, Error code is %d', [Name, es.dwError]);
    end;function TCustomRichEdit2.ReadFromStream(Stream : TStream; var Buffer; var Count : Longint) : Longint;
    begin
    Count := Stream.Read(Buffer, Count);
    Result := 0;
    end;function TCustomRichEdit2.WriteToStream(Stream : TStream; const Buffer; var Count : Longint) : Longint;
    begin
    Count := Stream.Write(Buffer, Count);
    Result := 0;
    end;// *** IRichEditOleCallback methods ***
    function TCustomRichEdit2.GetNewStorage(out lplpstg : IStorage) : HRESULT; stdcall;
    var
    LockBytes: ILockBytes;
    begin
    Result := E_NOTIMPL;
    if FPlainTextMode then Exit;
    Result:= S_OK;
    try
    OleCheck(CreateILockBytesOnHGlobal(0, True, LockBytes));
    OleCheck(StgCreateDocfileOnILockBytes(LockBytes, STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, lplpstg));
    except
    Result:= E_OUTOFMEMORY;
    end;
    end;
    {$IFDEF USES_IPACTIVATE}
    // Copy from VCL
    function GetVCLFrameForm(Form: TCustomForm): IVCLFrameForm;
    begin
    if Form.OleFormObject = nil then TOleForm.Create(Form);
    Result := Form.OleFormObject as IVCLFrameForm;
    end;// Copy from VCL
    function IsFormMDIChild(Form: TCustomForm): Boolean;
    begin
      Result := (Form is TForm) and (TForm(Form).FormStyle = fsMDIChild);
    end;
    {$ENDIF}function TCustomRichEdit2.GetInPlaceContext(out lplpFrame : IOleInplaceFrame;
    out lplpDoc : IOleInplaceUIWindow;
    var lpFrameInfo : OLEINPLACEFRAMEINFO) : HRESULT; stdcall;
    begin
    {$IFDEF USES_IPACTIVATE}
    lplpDoc := GetVCLFrameForm(ValidParentForm(Owner as TControl));
    lplpFrame := lplpDoc as IOleInplaceFrame;
    if IsFormMDIChild(GetVCLFrameForm(ValidParentForm(Owner as TControl)).Form) then
    begin
    lplpFrame := GetVCLFrameForm(Application.MainForm);
    end; with lpFrameInfo do
    begin
    cb := sizeof(lpFrameInfo);
    fMDIApp := False;
    lplpFrame.GetWindow(hWndFrame);
    hAccel := 0;
    cAccelEntries := 0;
    end;
    lpFrameInfo := lpFrameInfo; Result:= S_OK;
    {$ELSE}
    Result := E_NOTIMPL;
    {$ENDIF}
    end;function TCustomRichEdit2.ShowContainerUI(fShow : BOOL) : HRESULT; stdcall;
    begin
    {$IFDEF USES_IPACTIVATE}
    if fShow then
    with GetVCLFrameForm(ValidParentForm(Owner as TControl)) do
    begin
    SetMenu(0, 0, 0);
    ClearBorderSpace;
    end;
    {$ENDIF}
    Result := S_OK;
    end;function TCustomRichEdit2.QueryInsertObject(var lpclsid : TGUID; lpstg : IStorage; cp : LONG) : HRESULT; stdcall;
    begin
    Result := S_OK;
    if FPlainTextMode then
    begin
    Result := S_FALSE;
    Exit;
    end;
    end;function TCustomRichEdit2.DeleteObject(lpoleobj : IOleObject) : HRESULT; stdcall;
    begin
    Result := S_OK;
    end;function TCustomRichEdit2.QueryAcceptData(lpoleobj : IOleObject;
    var lpcfFormat : TClipFormat;
    reco : DWORD;
    fReally : BOOL;
    hMetaPict : HGLOBAL) : HRESULT; stdcall;
    begin
    if FPlainTextMode then
    lpcfFormat := CF_TEXT;
    Result := S_OK;
    end;function TCustomRichEdit2.ContextSensitiveHelp(fEnterMode : BOOL) : HRESULT; stdcall;
    begin
    Result := E_NOTIMPL;
    end;function TCustomRichEdit2.GetClipboardData(var lpchrg : CHARRANGE;
    reco : DWORD;
    out lplpdataobj : IDataObject) : HRESULT; stdcall;
    begin
    Result := E_NOTIMPL;
    end;function TCustomRichEdit2.GetDragDropEffect(fDrag : BOOL; grfKeyState : DWORD; var pdwEffect : DWORD) : HRESULT; stdcall;
    const
    MK_ALT = $20;
    begin
    pdwEffect := 0;
    if(fDrag=True) then
    begin
    pdwEffect := DROPEFFECT_SCROLL or DROPEFFECT_COPY or DROPEFFECT_MOVE;
    end
    else
    begin
    if(MK_CONTROL and grfKeyState) = MK_CONTROL then
    pdwEffect := pdwEffect or DROPEFFECT_COPY
    else
    pdwEffect := pdwEffect or DROPEFFECT_MOVE;
    end;
    Result := S_OK;
    end;function TCustomRichEdit2.GetContextMenu(seltype : WORD; lpoleobj : IOleObject; var lpchrg : CHARRANGE; var lphmenu : HMENU) : HRESULT; stdcall;
    var
    pt : TPoint;
    Handled : Boolean;
    begin
    Handled := False;
    GetCursorPos(pt);
    if Assigned(OnContextPopup) then
    begin
    Handled := False;
    OnContextPopup(Self, pt, Handled);
    end;
    if not Handled and Assigned(PopupMenu) then
    PopupMenu.Popup(pt.X, pt.Y);
    Result := E_NOTIMPL;
    end;procedure Register;
    begin
    RegisterComponents('Win32', [TRichEdit2]);
    end;end.
    自己建个包,添加这3个文件