今天在整理自己以前写的×××的时候,在RICHEDIT中插入图片的方法想不起来了。因此在网上找了一番,现将找的文章记录下来便于以后再次查找呵呵。
 
许多人在找RichEdit中插入GIF图片的方法,这里摘录一段我的一个程序的片段,
程序中使用了QQ中的OleImage.dll,要先象安装OCX控件一样安装,安装后产生一ImageOleLib_TLB文件,
要加入到工程中,并要安装rxRichEdit控件。
首先加入一单元InsRich(见下),再调用函数InsertGif(见下),下面还摘选了一段我使用的
代码。

unit InsRich;

interface
uses
   Windows, Messages, ActiveX;
const
   REO_CP_SelectION = ULONG(-1);
   REO_BELOWBASELINE = $00000002;
   REO_RESIZABLE = $00000001;
   REO_STATIC = $40000000;
   EM_GETOLEINTERFACE = WM_USER + 60;
   IID_IUnknown: TGUID = (D1: $00000000; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
   IID_IOleObject: TGUID = (D1: $00000112; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
type
   _ReObject = record
     cbStruct: DWORD; { Size of structure }
     cp: ULONG; { Character position of Object }
     clsid: TCLSID; { Class ID of Object }
     pOleObj: IOleObject; { Ole Object interface }
     pstg: IStorage; { Associated storage interface }
     pOleSite: IOleClientSite; { Associated Client Site interface }
     sizel: TSize; { Size of Object (may be 0,0) }
     dvAspect: Longint; { Display aspect to use }
     dwFlags: DWORD; { Object status flags }
     dwUser: DWORD; { Dword for user憇 use }
   end;
   TReObject = _ReObject;
   TCharRange = record {Copy From RichEdit.pas}
     cpMin: Integer;
     cpMax: Integer;
   end;
   TFormatRange = record
     hdc: Integer;
     hdcTarget: Integer;
     rectRegion: TRect;
     rectPage: TRect;
     chrg: TCharRange;
   end;
   IRichEditOle = interface(System.IUnknown)
     ['{00020d00-0000-0000-c000-000000000046}']
     function GetClientSite(out ClientSite: IOleClientSite): HResult; stdcall;
     function GetObjectCount: HResult; stdcall;
     function GetLinkCount: HResult; stdcall;
     function GetObject(iob: Longint; out ReObject: TReObject; dwFlags: DWORD): HResult; stdcall;
     function InsertObject(var ReObject: TReObject): HResult; stdcall;
     function ConvertObject(iob: Longint; rclsidNew: TIID; lpstrUserTypeNew: LPCSTR): HResult; stdcall;
     function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; stdcall;
     function SetHostNames(lpstrContainerApp: LPCSTR; lpstrContainerObj: LPCSTR): HResult; stdcall;
     function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; stdcall;
     function SetDvaspect(iob: Longint; dvAspect: DWORD): HResult; stdcall;
     function HandsOffStorage(iob: Longint): HResult; stdcall;
     function SaveCompleted(iob: Longint; const stg: IStorage): HResult; stdcall;
     function InPlaceDeactivate: HResult; stdcall;
     function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
     function GetClipboardData(var chrg: TCharRange; reco: DWORD; out dataObj: IDataObject): HResult; stdcall;
     function ImportDataObject(dataObj: IDataObject; cf: TClipFormat; hMetaPict: HGLOBAL): HResult; stdcall;
   end;
implementation
end.

插入到re中,sFileName是GIF图的路径,dwUser是标识别,用一随机数。
procedure InsertGif(re: TRxRichEdit; sFileName: string; dwUser: integer);
type
   tagSize = TSize;
var
   FRTF: IRichEditOle;
   FLockBytes: ILockBytes;
   FStorage: ISTORAGE;
   FClientSite: IOLECLIENTSITE;
   m_lpObject: IOleObject;
   m_lpAnimator: TGifAnimator;
   i_GifAnimator: IGifAnimator;
   reobject: TReObject;
   clsid: TGuid;
   sizel: tagSize;
   Rect: TRect;
begin
   try
     if CreateILockBytesOnHGlobal(0, True, FLockBytes) <> S_OK then
     begin
       //showmessage('Error to create Global Heap');
       exit;
     end;
   //????????????
     if StgCreateDocfileOnILockBytes(FLockBytes, STGM_SHARE_EXCLUSIVE or
       STGM_Create or STGM_READWRITE, 0, FStorage) <> S_OK then
     begin
       //Showmessage('Error to create storage');
       exit;
     end;
   //??RichEdit???
     Sendmessage(re.handle, EM_GETOLEINTERFACE, 0, LongInt(@FRTF));

     if FRTF.GetClientSite(FClientSite) <> S_OK then
     begin
       //ShowMessage('Error to get ClentSite');
       Exit;
     end;
     CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
     m_lpAnimator := TGifAnimator.Create(re);
     i_GifAnimator := m_lpAnimator.ControlInterface;
     i_GifAnimator.LoadFromFile(sFileName);
     i_GifAnimator.QueryInterface(IID_IOleObject, m_lpObject);
     OleSetContainedObject(m_lpObject, True);
     FillChar(ReObject, SizeOf(ReObject), 0);
     ReObject.cbStruct := SizeOf(ReObject);
     m_lpObject.GetUserClassID(clsid);
     ReObject.clsid := clsid;
     reobject.cp := REO_CP_SelectION;
   //content, but not static
     reobject.dvaspect := DVASPECT_CONTENT;
   //goes in the same line of text line
     reobject.dwFlags := REO_BELOWBASELINE; //REO_RESIZABLE |
     reobject.dwUser := 0;
   //the very object
     reobject.poleobj := m_lpObject;
   //client site contain the object
     reobject.polesite := FClientSite;
   //the storage
     reobject.pstg := FStorage;
     sizel.cx := 0;
     sizel.cy := 0;
     reobject.sizel := sizel;

   //Sel all text
     re.SelText := '';
     re.SelLength := 0;
     re.SelStart := re.SelStart;
     reobject.dwUser := dwUser;

   //Insert after the line of text
     FRTF.InsertObject(reobject);
     SendMessage(re.Handle, EM_SCROLLCARET, 0, 0);
   //VARIANT_BOOL ret;
   //do frame changing
     m_lpAnimator.TriggerFrameChange();
   //show it
     m_lpObject.DoVerb(OLEIVERB_UIACTIVATE, nil, FClientSite, 0, re.Handle, Rect);
// m_lpObject.DoVerb(
     m_lpObject.DoVerb(OLEIVERB_SHOW, nil, FClientSite, 0, re.Handle, Rect);
   //redraw the window to show animation
     RedrawWindow(re.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or RDW_ERASENOW or RDW_ALLCHILDREN);
   finally
     FRTF := nil;
     FClientSite := nil;
     FStorage := nil;
   end;
end;

以下是我程序中使用该函数的代码,供大家参考。
procedure TTextObject.AddGif(re: TRxRichEdit; sFile, sShortCut: string);
var
   GifIDMap: TGifIDMap;
   i, iGifID: integer;
   sFileName: string;
begin
   if Pos('\customface\', LowerCase(sFile)) <> 0 then
     sFileName := ExtractFilePath(Application.ExeName) + sNumber + sFile
   else
     sFileName := ExtractFilePath(Application.ExeName) + sFile;

   if not FileExists(sFileName) then Exit; // 文件不存在

   Randomize;
   iGifID := Random(2147483647);
   i := 0;
   while i < GifIDList.Count do
   begin
     if TGifIDMap(GifIDList.Items).iGifID = iGifID then
     begin
       iGifID := Random(2147483647);
       i := 0;
       Continue;
     end;
     Inc(i);
   end;
   InsertGif(re, sFileName, iGifID);// 调用
   GifIDMap := TGifIDMap.Create;
   GifIDMap.iGifID := iGifID;
   GifIDMap.sFileName := sFile;
   GifIDMap.sShortCut := sShortCut;
   GifIDList.Add(GifIDMap);
end;

procedure TTextObject.ShowRichEdit(re: TRxRichEdit; sHeadStr: string);
var
   i, iGifID, iCp: integer;
   iShift: integer;
   sFileName: string;
begin
   re.Lines.BeginUpdate;

   // 图行位置偏移量
   iShift := Length(sHeadStr);

   // 文本
   re.Lines.BeginUpdate;
   re.Clear;
   re.Text := sHeadStr + Text;
   re.Lines.EndUpdate;

   // 插入Gif
   for i := 0 to OleObjectList.Count - 1 do
   begin
     iCp := TOleObjectMap(OleObjectList.Items).iCp;
     iGifID := TOleObjectMap(OleObjectList.Items).iGifID;
     sFileName := GetFileName(iGifID);

     if sFileName <> '' then // 文件存在时
     begin
       re.SelStart := iCp + iShift;
       re.SelLength := 1;
       re.SelText := '';
       InsertGif(re, sFileName, iGifID); // 插入
     end;
   end;

   re.Lines.EndUpdate;
end;