Code:

uses

  RichEdit;

 

procedure TForm1.Button1Click(Sender: TObject);

var

  fmt: TParaformat2;

begin

  FillChar(fmt, SizeOf(fmt), 0);

  fmt.cbSize := SizeOf(fmt);

  // The PARAFORMAT2 structure is used to set the numbering style.

// This is done through the following structure members:

fmt.dwMask := PFM_NUMBERING or PFM_NUMBERINGSTART or PFM_NUMBERINGSTYLE or

                PFM_NUMBERINGTAB;

      // Set the following values (bitwise-or them together) to identify

     // which of the remaining structure members are valid:

     // PFM_NUMBERING, PFM_NUMBERINGSTART, PFM_NUMBERINGSTYLE, and PFM_NUMBERINGTAB

fmt.wNumbering := 2;

      //0 no numbering or bullets

     //1 (PFN_BULLET) uses bullet character

     //2 Uses Arabic numbers (1, 2, 3, ...).

     //3 Uses lowercase letters (a, b, c, ...).

     //4 Uses uppercase letters (A, B, C, ...).

     //5 Uses lowercase Roman numerals (i, ii, iii, ...).

     //6 Uses uppercase Roman numerals (I, II, III, ...).

     //7 Uses a sequence of characters beginning with the Unicode

     //  character specified by the wNumberingStart member.

fmt.wNumberingStart := 1;

      //  Starting value for numbering.

fmt.wNumberingStyle := $200;

      // Styles for numbering:

     // 0 : Follows the number with a right parenthesis.  1)

     // $100 : Encloses the number in parentheses.       (1)

     // $200 : Follows the number with a period.          1.

     // $300 : Displays only the number.                  1

     // $400 : Continues a numbered list without applying the next number or bullet.

     // $8000 : Starts a new number with wNumberingStart.

fmt.wNumberingTab := 1440 div 4;

  // Minimum space between a paragraph number and the paragraph text, in twips

 

RichEdit1.Perform(EM_SETPARAFORMAT, 0, lParam(@fmt));

end;

 

Code:

function RE_GetLastVisibleLine(RichEdit: TRichEdit): Integer;

const

  EM_EXLINEFROMCHAR = WM_USER + 54;

var

  r: TRect;

  i: Integer;

begin

  {

  The EM_GETRECT message retrieves the formatting rectangle

  of an edit control.

}

  RichEdit.Perform(EM_GETRECT, 0, Longint(@r));

  r.Left := r.Left + 1;

  r.Top  := r.Bottom - 2;

  {

   The EM_CHARFROMPOS message retrieves information about the character

   closest to a specified point in the client area of an edit control

}

  i := RichEdit.Perform(EM_CHARFROMPOS, 0, Integer(@r.topleft));

  {

   The EM_EXLINEFROMCHAR message determines which

   line contains the specified character in a rich edit control

}

  Result := RichEdit.Perform(EM_EXLINEFROMCHAR, 0, i);

end;

 

{

Sending the EM_GETFIRSTVISIBLELINE message to a multi-line edit control

finds out which line is the first line visible.

This is the line that is currently displayed at the top of the control.

}

 

function RE_GetFirstVisibleLine(RichEdit: TRichEdit): Integer;

begin

  Result := RichEdit.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);

end;

 

 

Code:

uses

  RichEdit;

 

// Underline styles

const

  CFU_UNDERLINETHICK = 9;

  CFU_UNDERLINEWAVE = 8;

  CFU_UNDERLINEDASHDOTDOT = 7;

  CFU_UNDERLINEDASHDOT = 6;

  CFU_UNDERLINEDASH = 5;

  CFU_UNDERLINEDOTTED = 4;

  CFU_UNDERLINE = 1;

  CFU_UNDERLINENONE = 0;

 

procedure RE_SetCharFormat(ARichEdit: TRichEdit; AUnderlineType: Byte; AColor: Word);

var

  // The CHARFORMAT2 structure contains information about

// character formatting in a rich edit control.

Format: CHARFORMAT2;

begin

  FillChar(Format, SizeOf(Format), 0);

  with Format do

  begin

    cbSize := SizeOf(Format);

    dwMask := CFM_UNDERLINETYPE;

    bUnderlineType := AUnderlineType or AColor;

    ARichEdit.Perform(EM_SETCHARFORMAT, SCF_SELECTION, Longint(@Format));

  end;

end;

 

// Underline the current selection with a CFU_UNDERLINEWAVE line style (color red);

procedure TForm1.Button1Click(Sender: TObject);

begin

  RE_SetCharFormat(RichEdit1, CFU_UNDERLINEWAVE, $50);

end;

Code:

unit RichEditPreview;

 

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, ExtCtrls, Printers, RichEdit, Menus, ComCtrls, ToolWin;

 

type

  TPageOffset = record

    mStart, mEnd: Integer;

    rendRect: TRect;

  end;

 

  TPreviewForm = class(TForm)

    Panel1: TPanel;

    Panel2: TPanel;

    procedure FormCreate(Sender: TObject);

    procedure FormDestroy(Sender: TObject);

    procedure FormResize(Sender: TObject);

  private

    { Private-Deklarationen }

  public

    { Public-Deklarationen }

    PreviewPanel: TPanel;

    procedure DrawRichEdit;

  end;

 

  TPreviewPanel = class(TPanel)

  private

 

  public

    constructor Create(Owner: TComponent); override;

    destructor Destroy; override;

    procedure Paint; override;

    property Canvas;

  end;

 

var

  PreviewForm: TPreviewForm;

 

implementation

 

uses Unit1, RxRichEd;

 

{$R *.dfm}

 

procedure TPreviewForm.FormCreate(Sender: TObject);

begin

  PreviewPanel := TPreviewPanel.Create(Self);

  PreviewPanel.Parent := Self;

  PreviewPanel.Color := clWhite;

end;

 

procedure TPreviewForm.FormDestroy(Sender: TObject);

begin

  if PreviewPanel <> nil then PreviewPanel.Free

end;

 

// We want the TPreviewPanel to approximate the scaled dimensions of the printed page.

// Whenever the parent

// form is resized, we need to rescale and center the panel on the form.

// To do this, add an OnResize event to

// the form and add the following code:

 

procedure TPreviewForm.FormResize(Sender: TObject);

var

   wPage, hPage, wClient, hClient: integer;

begin

  // get the printer dimensions

wPage := GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);

  hPage := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);

  // get the client window dimensions.

hClient := Panel2.ClientHeight;

  // initially adjust width to match height

wClient := MulDiv(Panel2.ClientHeight, wPage, hPage);

  // if that doesn't fit, then do it the other way

if wClient > Panel2.ClientWidth then

   begin

    wCLient := Panel2.ClientWidth;

    hClient := MulDiv(Panel2.ClientWidth, hPage, wPage);

    // center the page in the window

   PreviewPanel.Top := ((Panel2.ClientHeight - hClient) div 2) - Panel1.Height;

  end

  else

   begin

    // center the page in the window

   PreviewPanel.Left := (Panel2.ClientWidth - wClient) div 2;

    PreviewPanel.Top  := Panel1.Height;

  end;

  // now set size of panel

PreviewPanel.Width  := wClient;

  PreviewPanel.Height := hClient

end;

 

// The DrawRichEdit() method renders the contents of

// the control on the preview panel.

// Much of the code is

// very close to the code used to print the control in Part 2.

// The first part of the method is identical to

// the printing code:

 

procedure TPreviewForm.DrawRichEdit;

var

   wPage, hPage, xPPI, yPPI, wTwips, hTwips, currPage: integer;

  pageRect, rendRect, frameRect: TRect;

  po: TPageOffset;

  fr: TFormatRange;

  lastOffset, xOffset, yOffset, xPrinterOffset, yPrinterOffset: integer;

  FPageOffsets: array of TPageOffset;

  TextLenEx: TGetTextLengthEx;

  hdcDesktop, hdcCanvas, hdcPrinter, xDesktopPPI, yDesktopPPI,

  xFactor, yFactor: integer;

begin

  wPage := GetDeviceCaps(Printer.Handle, PHYSICALWIDTH);

  hPage := GetDeviceCaps(Printer.Handle, PHYSICALHEIGHT);

  xPPI := GetDeviceCaps(Printer.Handle, LOGPIXELSX);

  yPPI := GetDeviceCaps(Printer.Handle, LOGPIXELSY);

  wTwips := MulDiv(wPage, 1440, xPPI);

  hTwips := MulDiv(hPage, 1440, yPPI);

  with pageRect do

   begin

    Left := 0;

    Top := 0;

    Right := wTwips;

    Bottom := hTwips

  end;

  with rendRect do

   begin

    Left := 0;

    Top := 0;

    Right := pageRect.Right - (1440 * 4);

    Bottom := pageRect.Bottom - (1440 * 4)

  end;

  po.mStart := 0;

  // We will be using several device contexts (DCs),

// so let's go ahead and create variables for them.

hdcDesktop := GetWindowDC(GetDesktopWindow);

  hdcCanvas  := TPreviewPanel(PreviewPanel).Canvas.Handle;

  hdcPrinter := Printer.Handle;

  // Next, define and initialize a FORMATRANGE structure.

fr.hdc        := hdcDesktop;

  fr.hdcTarget  := hdcPrinter;

  fr.chrg.cpMin := po.mStart;

  fr.chrg.cpMax := -1;

  // We will need the size of the text in the control.

if RichEditVersion >= 2 then

   begin

    with TextLenEx do

     begin

      flags    := GTL_DEFAULT;

      codepage := CP_ACP;

    end;

    lastOffset := SendMessage(Form1.Editor.Handle, EM_GETTEXTLENGTHEX,

      wParam(@TextLenEx), 0)

  end

  else

     lastOffset := SendMessage(Form1.Editor.Handle, WM_GETTEXTLENGTH, 0, 0);

  // Clear the control's formatting buffer before rendering.

SendMessage(Form1.Editor.Handle, EM_FORMATRANGE, 0, 0);

  // Here is the tricky part.

// We need to scale the rendering DC to match the size of the printed page in

// printer device units.

SaveDC(hdcCanvas);

  SetMapMode(hdcCanvas, MM_TEXT);

  SetMapMode(hdcCanvas, MM_ANISOTROPIC);

  SetMapMode(hdcPrinter, MM_TEXT);

  SetWindowExtEx(hdcCanvas, pageRect.Right, pageRect.Bottom, nil);

  xDesktopPPI := GetDeviceCaps(hdcDesktop, LOGPIXELSX);

  yDesktopPPI := GetDeviceCaps(hdcDesktop, LOGPIXELSY);

  ScaleWindowExtEx(hdcCanvas, xDesktopPPI, 1440, yDesktopPPI, 1440, nil);

  SetViewportExtEx(hdcCanvas, PreviewPanel.ClientWidth, PreviewPanel.ClientHeight, nil);

  // Apparently, the Rich Edit control reduces the width of the

// rendering area by the amount of the left

// offset to the printable portion of the page when printing.

// This is a little odd to me because none of

// the Windows API GDI functions care whether you are printing

// within the printable portion of the page.

// Further, this occurs even though the rendering rectangle is

// already within the printable portion of the

// page.  Anyway, this does not seem to happen when the rendering

// DC is the screen so we need to manually

// adjust the rectangle ourselves.

xPrinterOffset  := MulDiv(GetDeviceCaps(hdcPrinter, PHYSICALOFFSETX), 1440, xPPI);

  yPrinterOffset  := MulDiv(GetDeviceCaps(hdcPrinter, PHYSICALOFFSETY), 1440, yPPI);

  rendRect.Left   := rendRect.Left + (xPrinterOffset shr 1);

  rendRect.Right  := rendRect.Right - xPrinterOffset - (xPrinterOFfset shr 1);

  rendRect.Top    := rendRect.Top + (yPrinterOffset shr 1);

  rendRect.Bottom := rendRect.Bottom - yPrinterOffset - (yPrinterOFfset shr 1);

  // Remember that we are hardcoding two-inch margins.

xOffset := MulDiv(PreviewPanel.ClientWidth shl 1, 1440, pageRect.Right);

  yOffset := MulDiv(PreviewPanel.ClientHeight shl 1, 1440, pageRect.Bottom);

  SetViewportOrgEx(hdcCanvas, xOffset, yOffset, nil);

  // Now we build the table of offsets.

// Note that we save the rendering rectangle returned by the format

// call.  When the rendering and target devices are the same

// (or the target device is set to zero), the

// returned rectangle is not really needed.

// In that case, you can simply ask the control to print to the

// original rendering rectangle.  However, when the devices are different,

// the returned rendering rectangle

// is sometimes larger than the requested rectangle.

// This must be a bug in the Rich Edit control.  We deal

// with it by saving the returned value to use when

// we actually render the control to the screen.

while ((fr.chrg.cpMin <> -1) and (fr.chrg.cpMin < lastOffset)) do

   begin

    fr.rc         := rendRect;

    fr.rcPage     := pageRect;

    po.mStart     := fr.chrg.cpMin;

    fr.chrg.cpMin := SendMessage(Form1.Editor.Handle, EM_FORMATRANGE, 0, Longint(@fr));

    po.mEnd       := fr.chrg.cpMin - 1;

    po.rendRect   := fr.rc;

    if High(FPageOffsets) = -1 then SetLength(FPageOffsets, 1)

    else

       SetLength(FPageOffsets, Length(FPageOffsets) + 1);

    FPageOffsets[High(FPageOffsets)] := po

  end;

  // If we were writing a fully working preview function,

// we could use FPageOffsets.size() to determine how

// many pages had been formatted.

// We would then set currPage (below) to the page that we wanted to

// display.

// In this example, however, we are going to display only the first page.

currPage := 0;

  // Now we set the rendering device to the panel's canvas.

// Since we have not cleared the formatting buffer,

// the target device is not needed, so we set it to zero.

// Then we fill in the remaining parts of the

// FORMATRANGE structure with the values we saved in FPageOffsets.

// Finally, we render the text to the

// screen (WPARAM is non-zero).

fr.hdc := hdcCanvas;

  fr.hdcTarget  := 0;

  fr.rc := FPageOffsets[currPage].rendRect;

  fr.rcPage := pageRect;

  fr.chrg.cpMin := FPageOffsets[currPage].mStart;

  fr.chrg.cpMax := FPageOffsets[currPage].mEnd;

  fr.chrg.cpMin := SendMessage(Form1.Editor.Handle, EM_FORMATRANGE, 1, Longint(@fr));

  // As I mentioned, the text may be drawn outside of the rendering rectangle.

// To make that easier to see,

// let's draw a rectangle that shows where the rendering rectangle should be

SetMapMode(hdcCanvas, MM_TEXT);

  SetViewportOrgEx(hdcCanvas, 0, 0, nil);

  frameRect := rendRect;

  OffsetRect(frameRect, 1440 + 1440, 1440 + 1440);

  xFactor          := MulDiv(PreviewPanel.ClientWidth,

    (pageRect.Right - rendRect.Right) shr 1, pageRect.Right);

  yFactor          := MulDiv(PreviewPanel.ClientHeight,

    (pageRect.Bottom - rendRect.Bottom) shr 1, pageRect.Bottom);

  frameRect.Left   := xFactor;

  frameRect.Right  := PreviewPanel.ClientWidth - xFactor;

  frameRect.Top    := yFactor;

  frameRect.Bottom := PreviewPanel.ClientHeight - yFactor;

  Windows.FrameRect(hdcCanvas, frameRect, GetStockObject(BLACK_BRUSH));

  // To wrap up, we restore the panel's canvas to the original state,

// release the desktop DC, clear the Rich

// Edit control's formatting buffer, empty the page offset table,

   and Close the DrawRichEdit() method.RestoreDC(hdcCanvas, - 1);

  ReleaseDC(GetDesktopWindow, hdcDesktop);

  SendMessage(Form1.Editor.Handle, EM_FORMATRANGE, 0, 0);

  Finalize(FPageOffsets);

end;

 

(*****************************************************)

(* Alles uber den Nachfahren von TPanel              *)

(*****************************************************)

 

constructor TPreviewPanel.Create(Owner: TComponent);

begin

  inherited Create(Owner);

end;

 

destructor TPreviewPanel.Destroy;

begin

  inherited Destroy

end;

 

procedure TPreviewPanel.Paint;

begin

  inherited Paint;

  PreviewForm.DrawRichEdit;

end;

 

end.

 

Code:

var

  frmMain: TfrmMain;

 

implementation

 

{$R *.DFM}

{$R Smiley.res}

 

uses

  RichEdit;

 

type

  TEditStreamCallBack = function(dwCookie: Longint; pbBuff: PByte;

    cb: Longint; var pcb: Longint): DWORD;

  stdcall;

 

  TEditStream = record

    dwCookie: Longint;

    dwError: Longint;

    pfnCallback: TEditStreamCallBack;

  end;

 

type

  TMyRichEdit = TRxRichEdit;

 

// EditStreamInCallback callback function

 

function EditStreamInCallback(dwCookie: Longint; pbBuff: PByte;

  cb: Longint; var pcb: Longint): DWORD; stdcall;

var

  theStream: TStream;

  dataAvail: LongInt;

begin

  theStream := TStream(dwCookie);

  with theStream do

  begin

    dataAvail := Size - Position;

    Result := 0;

    if dataAvail <= cb then

    begin

      pcb := read(pbBuff^, dataAvail);

      if pcb <> dataAvail then

        Result := UINT(E_FAIL);

    end

    else

    begin

      pcb := read(pbBuff^, cb);

      if pcb <> cb then

        Result := UINT(E_FAIL);

    end;

  end;

end;

 

// Insert Stream into RichEdit

 

procedure PutRTFSelection(RichEdit: TMyRichEdit; SourceStream: TStream);

var

  EditStream: TEditStream;

begin

  with EditStream do

  begin

    dwCookie := Longint(SourceStream);

    dwError := 0;

    pfnCallback := EditStreamInCallBack;

  end;

  RichEdit.Perform(EM_STREAMIN, SF_RTF or SFF_SELECTION, Longint(@EditStream));

end;

 

// Load a smiley image from resource

 

function GetSmileyCode(ASimily: string): string;

var

  dHandle: THandle;

  pData, pTemp: PChar;

  Size: Longint;

begin

  pData := nil;

  dHandle := FindResource(hInstance, PChar(ASimily), RT_RCDATA);

  if dHandle <> 0 then

  begin

    Size := SizeofResource(hInstance, dHandle);

    dhandle := LoadResource(hInstance, dHandle);

    if dHandle <> 0 then

      try

        pData := LockResource(dHandle);

        if pData <> nil then

          try

            if pData[Size - 1] = #0 then

            begin

              Result := StrPas(pTemp);

            end

            else

            begin

              pTemp := StrAlloc(Size + 1);

              try

                StrMove(pTemp, pData, Size);

                pTemp[Size] := #0;

                Result := StrPas(pTemp);

              finally

                StrDispose(pTemp);

              end;

            end;

          finally

            UnlockResource(dHandle);

          end;

      finally

        FreeResource(dHandle);

      end;

  end;

end;

 

procedure InsertSmiley(ASmiley: string);

var

  ms: TMemoryStream;

  s: string;

begin

  ms := TMemoryStream.Create;

  try

    s := GetSmileyCode(ASmiley);

    if s <> '' then

    begin

      ms.Seek(0, soFromEnd);

      ms.Write(PChar(s)^, Length(s));

      ms.Position := 0;

      PutRTFSelection(frmMain.RXRichedit1, ms);

    end;

  finally

    ms.Free;

  end;

end;

 

procedure TfrmMain.SpeedButton1Click(Sender: TObject);

begin

  InsertSmiley('Smiley1');

end;

 

procedure TfrmMain.SpeedButton2Click(Sender: TObject);

begin

  InsertSmiley('Smiley2');

end;

 

// Replace a :-) or :-( with a corresponding smiley

 

procedure TfrmMain.RxRichEdit1KeyPress(Sender: TObject; var Key: Char);

var

sCode, SmileyName: string;

 

  procedure RemoveText(RichEdit: TMyRichEdit);

  begin

    with RichEdit do

    begin

      SelStart := SelStart - 2;

      SelLength := 2;

      SelText :=  '';

    end;

  end;

 

begin

If (Key = ')') or (Key = '('then

begin

   sCode := Copy(RxRichEdit1.Text, RxRichEdit1.SelStart-1, 2) + Key;

   SmileyName := '';

   if sCode = ':-)' then SmileyName := 'Smiley1';

   if sCode = ':-(' then SmileyName := 'Smiley2';

   if SmileyName <> '' then

   begin

     Key := #0;

     RemoveText(RxRichEdit1);

     InsertSmiley('Smiley1');

   end;

end;

end;

У меня есть 2 memo. как мне сделать так, чтобы в клипборд посылалосьтабличка из двух ячеек с содержимым их мемо. точнее как загнать табличку в клипборд программно.

Я смотрел, что когда копируешь из wordа табличку, то в клипе лежит текст и картинка (вот с эти я больше всего не понял). Не понятно!!

 

Итак во-первых

Мутим такую программку

Чтобы вывести Rich Edit на любой канвас, нужно использовать стандартное сообщение EM_FORMATRANGE.

lParam пареметр этого сообщения содержит указатель на структуру TFormatRange.

Перед посылкой сообщения нужно заполнить эту структуру:

hdc - контекст устройства, на который будет выводиться Rich Edit

hdcTarget - контекст устройства, в соответствии с которым будет производиться форматирование текста

rc - область, в которую будет выводиться Rich Edit. Единицы измерения - твипсы (twips). Twips = 1/1440 дюйма.

rcPage - полная область вывода устройства (в твипсах)

chrg - указывает диапазон выводимого текста

 

Узнать положение курсора в RichEdit не составляет труда (richedit.getcaret). А вот как установить каретку в нужное место?