zoukankan      html  css  js  c++  java
  • 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;
  • 相关阅读:
    Tomcat 中会话超时的相关配置
    Oracle10g任务调度创建步骤
    Oracle的三种高可用集群方案
    软/硬件负载均衡产品 你知多少?
    Nginx、LVS及HAProxy负载均衡软件的优缺点详解
    java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
    TortoiseSVN客户端重新设置用户名和密码
    Linux下oracle数据库启动和关闭操作
    Linux下使用ps命令来查看Oracle相关的进程
    【Kill】两条Linux命令彻底杀死Oracle
  • 原文地址:https://www.cnblogs.com/BTag/p/15666932.html
Copyright © 2011-2022 走看看