Richedit 插入对象并以图标 显示


function TfrmBillattachment.cxRicheditInsertFile(FilePath:string): Boolean; const REO_CP_SELECTION = $FFFFFFFF; REO_IOB_SELECTION = $FFFFFFFF; 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) ); REO_RESIZABLE = $00000001; // Object may be resized procedure ReleaseObject(var AObj); begin if IUnknown(AObj) <> nil then IUnknown(AObj)._Release; IUnknown(AObj) := nil; end; function GetOleMetaPict(AOleObject:IOleObject; ALable:string):HGlobal; var AClassID: TCLSID; begin Result := 0; OleCheck(AOleObject.GetUserClassID(AClassID)); Result := OleGetIconOfClass(AClassID, PWideChar(WideString(ALable)), False); end; var ReOle: IcxRichEditOle; OleSite: IOleClientSite; Storage: IStorage; SubSTG: IStorage; LockBytes: ILockBytes; OleObject: IOleObject; ReObj: TReObject; TempOle: IUnknown; FormatEtc: TFormatEtc; ASelection: TCharRange; IST :IStream; OST :TOLESTream; FileName :Pchar; FileName2 :array[1..1024] of char; FileM: TmemoryStream; IconMetaPict: HGlobal; begin Result := False; if not FileExists(FilePath) then Exit; if not cxRichEditGetOleInterface(TcxRichInnerEdit(cxDBRichEdit1.InnerControl).Handle,ReOle) then Exit; Assert(ReOle <> nil, 'RichEditOle is null!'); try ReOle.GetClientSite(OleSite); OleCheck(CreateILockBytesOnHGlobal(0, True, LockBytes)); Assert(LockBytes <> nil, 'LockBytes is null!'); OleCheck(StgCreateDocfileOnILockBytes(LockBytes, STGM_SHARE_EXCLUSIVE or STGM_CREATE or STGM_READWRITE, 0, Storage)); Assert(Storage <> nil, 'Storage is null!'); FormatEtc.dwAspect := DVASPECT_ICON; OleCheck(OleCreateFromFile(GUID_NULL, PWideChar(WideString(FilePath)), IID_IUnknown, 0, @FormatEtc, OleSite, Storage, TempOle)); OleCheck(TempOle.QueryInterface(IID_IOleObject, OleObject)); OleCheck(OleSetContainedObject(OleObject, True)); Assert(OleObject <> nil, 'OleObject is null!'); FillChar(ReObj, Sizeof(ReObj), 0); FileName := PansiCHar(ExtractFileName(FilePath)); olecheck( Storage.CreateStorage('substorage', stgm_create or stgm_write or stgm_share_exclusive, 0,0,subSTG)); //创建IStream //文件名 olecheck(substg.createstream('filename', stgm_create or stgm_write or stgm_share_exclusive, 0,0,IST)); //创建OLEStream OST:=TOLEStream.create(IST); OST.write(FileName^,length(string(FileName))); //写入数据 OST.Free; //文件内容 olecheck(substg.createstream('filecontent', stgm_create or stgm_write or stgm_share_exclusive, 0,0,IST)); //创建OLEStream FileM := TmemoryStream.Create; FileM.LoadFromFile(FilePath); FileM.Position := 0; OST:=TOLEStream.create(IST); OST.CopyFrom(FileM, FileM.size); OST.Free; FileM.Free; ReObj.cbStruct := Sizeof(ReObj); OleCheck(OleObject.GetUserClassID(ReObj.clsid)); ReObj.cp := REO_CP_SELECTION; ReObj.dvaspect := DVASPECT_CONTENT; ReObj.oleobj := OleObject; ReObj.olesite := OleSite; ReObj.stg := Storage; ReObj.dwUser := 0; ReObj.dwFlags := REO_RESIZABLE;//ULong(REO_STATIC) or ULong(REO_BELOWBASELINE); ReObj.sizel.cx := 0; ReObj.sizel.cy := 0; // if cxDBRichEdit1.Lines.Count =0 then // begin //// cxDBRichEdit1.Text := ExtractFileName(FilePath)+': '; //// cxDBRichEdit1.SelStart := Length(cxDBRichEdit1.Text); // end // else // begin // try // cxDBRichEdit1.Lines.Add(''); // except // end; // end; if TcxRichInnerEdit(cxDBRichEdit1.InnerControl).HandleAllocated then begin SendMessage(TcxRichInnerEdit(cxDBRichEdit1.InnerControl).Handle, EM_SCROLLCARET, 0, 0); end; if TcxRichInnerEdit(cxDBRichEdit1.InnerControl).HandleAllocated then begin SendMessage(TcxRichInnerEdit(cxDBRichEdit1.InnerControl).Handle, EM_EXGETSEL, 0, LPARAM(@ASelection)); ASelection.cpMax := ASelection.cpMin + 1; end; //获取该对象的图标 图片也是一样。不显示图片内容 IconMetaPict := GetOleMetaPict(OleObject, FileName); OleCheck(cxSetDrawAspect(OleObject, True, IconMetaPict, ReObj.dvaspect)); if Succeeded(ReOle.InsertObject(ReObj))then begin // if TcxRichInnerEdit(cxDBRichEdit1.InnerControl).HandleAllocated then // begin // SendMessage(TcxRichInnerEdit(cxDBRichEdit1.InnerControl).Handle, EM_EXSETSEL, 0, LPARAM(@ASelection)); // SendMessage(TcxRichInnerEdit(cxDBRichEdit1.InnerControl).Handle, EM_SCROLLCARET, 0, 0); // end; // ReOle.SetDvaspect(Longint(REO_IOB_SELECTION), ReObj.dvaspect); Result := True; end; // if Pos(ExtractFileExt(FilePath),'.doc,.docx,.xls,.xlsx') >0 then // begin // try // cxDBRichEdit1.Lines.Add(ExtractFileName(FilePath)); // except // end; // end; finally ReleaseObject(OleObject); ZeroMemory(@ReObj,SizeOf(ReObj)); // FileInfo.Free; qry_Data.Tag := 1; end; end;

 以下是摘抄dev的处理方式。

function cxSetDrawAspect(AOleObject: IOleObject; AIconic: Boolean;
  AIconMetaPict: HGlobal; var ADrawAspect: Cardinal): HResult;
var
  AOleCache: IOleCache;
  AEnumStatData: IEnumStatData;
  AOldAspect: Cardinal;
  AAdviseFlags, AConnection: Longint;
  ATempMetaPict: HGlobal;
  AFormatEtc: TFormatEtc;
  AMedium: TStgMedium;
  AClassID: TCLSID;
  AStatData: TStatData;
  AViewObject: IViewObject;
begin
  AOldAspect := ADrawAspect;
  if AIconic then
  begin
    ADrawAspect := DVASPECT_ICON;
    AAdviseFlags := ADVF_NODATA;
  end else
  begin
    ADrawAspect := DVASPECT_CONTENT;
    AAdviseFlags := ADVF_PRIMEFIRST;
  end;
  if (ADrawAspect <> AOldAspect) or (ADrawAspect = DVASPECT_ICON) then
  begin
    AOleCache := AOleObject as IOleCache;
    if ADrawAspect <> AOldAspect then
    begin
      OleCheck(AOleCache.EnumCache(AEnumStatData));
      if AEnumStatData <> nil then
        while AEnumStatData.Next(1, AStatData, nil) = 0 do
          if AStatData.formatetc.dwAspect = Integer(AOldAspect) then
            AOleCache.Uncache(AStatData.dwConnection);
      FillChar(AFormatEtc, SizeOf(FormatEtc), 0);
      AFormatEtc.dwAspect := ADrawAspect;
      AFormatEtc.lIndex := -1;
      OleCheck(AOleCache.Cache(AFormatEtc, AAdviseFlags, AConnection));
      if AOleObject.QueryInterface(IViewObject, AViewObject) = 0 then
        AViewObject.SetAdvise(ADrawAspect, 0, nil);
    end;
    if ADrawAspect = DVASPECT_ICON then
    begin
      ATempMetaPict := 0;
      if AIconMetaPict = 0 then
      begin
        OleCheck(AOleObject.GetUserClassID(AClassID));
        ATempMetaPict := OleGetIconOfClass(AClassID, nil, True);
        AIconMetaPict := ATempMetaPict;
      end;
      try
        with AFormatEtc do
        begin
          cfFormat := CF_METAFILEPICT;
          ptd := nil;
          dwAspect := DVASPECT_ICON;
          lindex := -1;
          tymed := TYMED_MFPICT;
        end;

        with AMedium do
        begin
          tymed := TYMED_MFPICT;
          hMetaFilePict :=  AIconMetaPict;
          unkForRelease := nil;                         
        end;

        OleCheck(AOleCache.SetData(AFormatEtc, AMedium, False));
      finally
        DestroyMetaPict(ATempMetaPict);
      end;
    end;
    if ADrawAspect <> DVASPECT_ICON then
      AOleObject.Update;
  end;
  Result := S_OK;
end;
function cxRichEditGetOleInterface(AH: HWnd; out AOleInterface: IcxRichEditOle): Boolean;
 begin
   Result := SendMessage(AH, EM_GETOLEINTERFACE, 0, LPARAM(@AOleInterface)) <> 0;
 end;

function cxRichEditSelectedIsPic(cxRichEdit: TcxRichEdit; out Pic: TPicture; IsOutPic: Boolean=False): Boolean;
var
  FRichEditOle: IUnknown;
  i: Integer;
  AReObject: TReObject;
  pDataObject: IDataObject;
  fm: TFormatEtc;
  em: IEnumFormatEtc;
  stg: TStgMedium;
  TmpPic1, TmpPic2: TPicture;
  g: TGPGraphics;
  img: TGPImage;
  MemStream: TMemoryStream;
  MyIStream: TStreamAdapter;
  RootSTG,SubSTG :IStorage;
begin
 Result := False;
 try
  FRichEditOle := nil;
  if not cxRichEditGetOleInterface(TcxRichInnerEdit(cxRichEdit.InnerControl).Handle,IcxRichEditOle(FRichEditOle)) then
    Exit;
  with IcxRichEditOle(FRichEditOle) do
  begin
   for i := 0 to GetObjectCount -1 do
   begin
     FillChar(AReObject, SizeOf(AReObject), 0);
     AReObject.cbStruct := SizeOf(AReObject);
     OleCheck(GetObject(LongInt(i), AReObject, REO_GETOBJ_ALL_INTERFACES));
     //不是选中状态跳过
     if (AReObject.dwFlags and REO_SELECTED) <> REO_SELECTED then
        Continue;
     pDataObject := nil;
     OleCheck(AReObject.oleobj.QueryInterface(IDataObject, pDataObject));
     if pDataObject <> nil then
     begin
       em := nil;
       pDataObject.EnumFormatEtc(DATADIR_GET, em);
       if em <> nil then
       begin
        FillChar(fm, SizeOf(fm), 0);
        while em.Next(1, fm, nil) <> S_FALSE do
        begin
          Result :=  fm.cfFormat in [CF_BITMAP, CF_DIB, CF_METAFILEPICT];
         if not Result then
          Break;
        end;
       end;
     end;
   end;
  end;
  if Result and IsOutPic then
  begin
   TmpPic1 := TPicture.Create;
   TmpPic2 := TPicture.Create;
   MemStream := TMemoryStream.Create;
   if fm.cfFormat in [CF_BITMAP,CF_DIB] then
   begin
    fm.cfFormat := CF_BITMAP;
    fm.ptd := nil;
    fm.dwAspect := DVASPECT_CONTENT;
    fm.lindex := -1;
    fm.tymed := TYMED_GDI;
    if Succeeded(pDataObject.GetData(fm, stg)) then
    begin
     TmpPic1.Bitmap.Handle := stg.hBitmap;
     TmpPic2.Bitmap.Width := TmpPic1.Bitmap.Width;
     TmpPic2.Bitmap.Height := TmpPic1.Bitmap.Height;
     TmpPic2.Bitmap.Canvas.CopyRect(TmpPic1.Bitmap.Canvas.ClipRect, TmpPic1.Bitmap.Canvas, TmpPic1.Bitmap.Canvas.ClipRect);
     TmpPic2.Bitmap.SaveToStream(MemStream);
     ReleaseStgMedium(stg);
    end;
   end //图元文件 以emf文件格式存在
   else if fm.cfFormat = CF_METAFILEPICT then
   begin
    SendMessage(TcxRichInnerEdit(cxRichEdit.InnerControl).Handle, WM_COPY, 0, 0);
    try
     if OpenClipboard(0) then
     begin
      TmpPic2.Metafile.LoadFromClipboardFormat(0,0,0);
      TmpPic2.Metafile.SaveToStream(MemStream);
      MemStream.Position := 0;
     end;
    finally
     CloseClipboard;
    end;
   end;
   MyIStream := TStreamAdapter.Create(MemStream);
   img := TGPImage.Create(MyIStream);
   pic := TPicture.Create;
   pic.Bitmap.Width := img.GetWidth;
   pic.Bitmap.Height :=img.GetHeight;
   g := TGPGraphics.Create(pic.Bitmap.Canvas.Handle);
    { 缩放时的算法模式 }
   g.SetInterpolationMode(TInterpolationMode(InterpolationModeHighQualityBicubic));
   g.DrawImage(img, MakeRect(0, 0, img.GetWidth, img.GetHeight), 0, 0, img.GetWidth, img.GetHeight, UnitPixel);
   g.Free;
   img.Free;
   FreeAndNil(MemStream);
   TmpPic1.Free;
   TmpPic2.Free;
  end;
 finally
  em := nil;
  pDataObject := nil;
  FRichEditOle := nil;
 end;
end;

 还有一种是自带的插入对话框

function cxRicheditInsertFile2(cxRichEdit: TcxCustomRichEdit; FilePath:string): Boolean;

 procedure ReleaseObject(var AObj);
 begin
   if IUnknown(AObj) <> nil then
     IUnknown(AObj)._Release;
   IUnknown(AObj) := nil;
 end;

 procedure cxCreateStorage(var AStorage: IStorage);
 var
  ALockBytes: ILockBytes;
 begin
  OleCheck(CreateILockBytesOnHGlobal(0, True, ALockBytes));
  OleCheck(StgCreateDocfileOnILockBytes(ALockBytes, STGM_READWRITE
    or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, AStorage));
  ReleaseObject(ALockBytes);
 end;

var
  AData: TOleUIInsertObject;
  ANameBuffer: array[0..255] of AnsiChar;
  RichEditOle: IcxRichEditOle;
  AOleClientSite: IOleClientSite;
  AStorage: IStorage;
  AReObject: TReObject;
  AOleObject: IOleObject;
  ASelection: TCharRange;
  AIsNewObject: Boolean;
  FormatEtc: TFormatEtc;
  TempOle: IOleObject;
begin
  Result := False;
//
  if not cxRichEditGetOleInterface(TcxRichInnerEdit(cxRichEdit.InnerControl).Handle,RichEditOle) then
    Exit;
  Assert(RichEditOle <> nil, 'RichEditOle is null!');
//
  FillChar(AData, SizeOf(AData), 0);
  FillChar(ANameBuffer, SizeOf(ANameBuffer), 0);
  AStorage := nil;
  try
    cxCreateStorage(AStorage);
    RichEditOle.GetClientSite(AOleClientSite);
    with AData do
    begin
      cbStruct := SizeOf(AData);
      dwFlags := IOF_SELECTCREATEFROMFILE or IOF_VERIFYSERVERSEXIST or
        IOF_CREATENEWOBJECT or IOF_CREATEFILEOBJECT or IOF_CREATELINKOBJECT or IOF_CHECKLINK or IOF_CHECKDISPLAYASICON;
      hWndOwner := cxRichEdit.InnerControl.Handle;
      lpfnHook := cxOleDialogHook;
      ANameBuffer := 'J:\源码\test\Richedit测试\1.docx';
      lpszFile := ANameBuffer;
//      lpszFile := PAnsiChar('J:\源码\test\Richedit测试\1.docx');
      cchFile := SizeOf(ANameBuffer);
      oleRender := OLERENDER_DRAW;
      iid := IOleObject;
      lpIOleClientSite := AOleClientSite;
      lpIStorage := AStorage;
      lpszCaption := PChar('选择文件');
//      lpszTemplate := pchar('test');
      ppvObj := @AOleObject;
//      lpszFile := PAnsiChar('J:\源码\test\Richedit测试\1.docx');
    end;
    if {$IFDEF DELPHI12}OleUIInsertObjectA{$ELSE}OleUIInsertObject{$ENDIF}(AData) = OLEUI_OK then
      try

//        AData.lpszFile := PAnsiChar(FilePath);
//        FillChar(AReObject, SizeOf(AReObject), 0);
//
//        FormatEtc.dwAspect := DVASPECT_ICON;
//        OleCheck(OleCreateFromFile(GUID_NULL, PWideChar(WideString(FilePath)),
//        IID_IUnknown, 0, @FormatEtc, AOleClientSite, AStorage, TempOle));
//
//        OleCheck(TempOle.QueryInterface(IID_IOleObject, AOleObject));
//        OleCheck(OleSetContainedObject(AOleObject, True));
//        AOleObject.SetClientSite(AOleClientSite);
//        OleCheck(AOleObject.GetUserClassID(AReObject.clsid));

        with AReObject do
        begin
          cbStruct := SizeOf(AReObject);
          cp := REO_CP_SELECTION;
          oleobj := AOleObject;
          stg := AStorage;
          olesite := AOleClientSite;
          dvaspect := DVASPECT_CONTENT;
          dwFlags := REO_RESIZABLE;
          AReObject.sizel.cx := 0;
          AReObject.sizel.cy := 0;
        end;

        OleCheck(SetDrawAspect(AOleObject, True, 0, AReObject.dvaspect));

//        if HandleAllocated then
//        begin
//          SendMessage(Handle, EM_EXGETSEL, 0, LPARAM(@ASelection));
//          ASelection.cpMax := ASelection.cpMin + 1;
//        end;
        if Succeeded(RichEditOle.InsertObject(AReObject)) then
        begin
//          if HandleAllocated then
//          begin
//            SendMessage(Handle, EM_EXSETSEL, 0, LPARAM(@ASelection));
//            SendMessage(Handle, EM_SCROLLCARET, 0, 0);
//          end;
          RichEditOle.SetDvaspect(Longint(REO_IOB_SELECTION), AReObject.dvaspect);
//          if AIsNewObject then OleCheck(AReObject.oleobj.DoVerb(OLEIVERB_SHOW, nil,
//            AOleClientSite, 0, Handle, ClientRect));
          Result := True;
        end;
      finally
        DestroyMetaPict(AData.hMetaPict);
        ReleaseObject(AOleObject);
        ZeroMemory(@AReObject,SizeOf(AReObject));
      end;
  finally
    ZeroMemory(@AData,SizeOf(AData));
  end;

end;
原文地址:https://www.cnblogs.com/BTag/p/15666932.html