zoukankan      html  css  js  c++  java
  • 让DELPHI自带的richedit控件显示图片

    让DELPHI自带的richedit控件显示图片

    unit RichEx;
    
    {
    2005-03-04 LiChengbin
    Added:
    Insert bitmap or gif into RichEdit controls from source file.
    
    2005-01-31 LiChengbin
    Usage:
    Insert bitmap into RichEdit controls by IRichEditOle interface and
    implementation of IDataObject interface.
    
    Example:
    InsertBitmap(RichEdit1.Handle, Image1.Picture.Bitmap);
    }
    
    interface
    
    uses
      Windows, Messages, Graphics, ActiveX, ComObj;
    
    const
    
      // 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 = $FFFFFFFF;
    
      // Use character position to specify object instead of index
      REO_IOB_SELECTION = $FFFFFFFF;
      REO_IOB_USE_CP = $FFFFFFFF;
    
      // 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;                     // drag
    
      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)
      );
      IID_IGifAnimator: TGUID = '{0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16}';
      CLASS_GifAnimator: TGUID = '{06ADA938-0FB0-4BC0-B19B-0A38AB17F182}';
    
    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's use         }
      end;
    
      TReObject = _ReObject;
    
      TCharRange = record
        cpMin: Integer;
        cpMax: Integer;
      end;
    
      TFormatRange = record
        hdc: Integer;
        hdcTarget: Integer;
        rectRegion: TRect;
        rectPage: TRect;
        chrg: TCharRange;
      end;
    
      IRichEditOle = interface(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;
    
      // *********************************************************************//
      // interface: IGifAnimator
      // Flags:   (4544) Dual NonExtensible OleAutomation Dispatchable
      // GUID:     {0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16}
      // *********************************************************************//
      IGifAnimator = interface(IDispatch)
        ['{0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16}']
        procedure LoadFromFile(const FileName: WideString); safecall;
        function TriggerFrameChange: WordBool; safecall;
        function GetFilePath: WideString; safecall;
        procedure ShowText(const Text: WideString); safecall;
      end;
    
      // *********************************************************************//
      // DispIntf: IGifAnimatorDisp
      // Flags:   (4544) Dual NonExtensible OleAutomation Dispatchable
      // GUID:     {0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16}
      // *********************************************************************//
      IGifAnimatorDisp = dispinterface
        ['{0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16}']
        procedure LoadFromFile(const FileName: WideString); dispid 1;
        function TriggerFrameChange: WordBool; dispid 2;
        function GetFilePath: WideString; dispid 3;
        procedure ShowText(const Text: WideString); dispid 4;
      end;
    
      TBitmapOle = class(TInterfacedObject, IDataObject)
      private
        FStgm: TStgMedium;
        FFmEtc: TFormatEtc;
        procedure SetBitmap(hBitmap: HBITMAP);
        procedure GetOleObject(OleSite: IOleClientSite; Storage: IStorage; var OleObject: IOleObject);
      public
        { ======================================================================= }
        { implementation of IDataObject interface }
        function GetData(const formatetcIn: TFormatEtc; out medium: TStgMedium): HResult; stdcall;
        function GetDataHere(const formatetc: TFormatEtc; out medium: TStgMedium): HResult; stdcall;
        function QueryGetData(const formatetc: TFormatEtc): HResult; stdcall;
        function GetCanonicalFormatEtc(const formatetc: TFormatEtc; out formatetcOut: TFormatEtc): HResult; stdcall;
        function SetData(const formatetc: TFormatEtc; var medium: TStgMedium; fRelease: BOOL): HResult; stdcall;
        function EnumFormatEtc(dwDirection: Longint; out enumFormatEtc: IEnumFormatEtc): HResult; stdcall;
        function DAdvise(const formatetc: TFormatEtc; advf: Longint; const advSink: IAdviseSink; out dwConnection: Longint): HResult; stdcall;
        function DUnadvise(dwConnection: Longint): HResult; stdcall;
        function EnumDAdvise(out enumAdvise: IEnumStatData): HResult; stdcall;
        { ======================================================================= }
      end;
    
    function InsertBitmap(hRichEdit: THandle; const FileName: string): Boolean; overload;
    
    function InsertBitmap(hRichEdit: THandle; Bitmap: TBitmap): Boolean; overload;
    
    function InsertGif(hRichEdit: THandle; const FileName: string): Boolean;
    
    implementation
    
    function GetRichEditOle(hRichEdit: THandle): IRichEditOle;
    begin
      SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, Longint(@Result));
    end;
    
    function GetImage(Bitmap: TBitmap): HBITMAP;
    var
      Dest: HBitmap;
      DC, MemDC: HDC;
      OldBitmap: HBITMAP;
    begin
      DC := GetDC(0);
      MemDC := CreateCompatibleDC(DC);
      try
        Dest := CreateCompatibleBitmap(DC, Bitmap.Width, Bitmap.Height);
        OldBitmap := SelectObject(MemDC, Dest);
        BitBlt(MemDC, 0, 0, Bitmap.Width, Bitmap.Height, Bitmap.Canvas.Handle, 0, 0, SRCCOPY);
        SelectObject(MemDC, OldBitmap);
      finally
        DeleteDC(MemDC);
        ReleaseDC(0, DC);
      end;
      Result := Dest;
    end;
    
    function TBitmapOle.GetData(const formatetcIn: TFormatEtc; out medium: TStgMedium): HResult; stdcall;
    begin
      medium.tymed := TYMED_GDI;
      medium.hBitmap := OleDuplicateData(FStgm.hBitmap, CF_BITMAP, 0);
      medium.unkForRelease := nil;
      if medium.hBitmap = 0 then
        Result := E_HANDLE
      else
        Result := S_OK;
    end;
    
    function TBitmapOle.GetDataHere(const formatetc: TFormatEtc; out medium: TStgMedium): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    function TBitmapOle.QueryGetData(const formatetc: TFormatEtc): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    function TBitmapOle.GetCanonicalFormatEtc(const formatetc: TFormatEtc; out formatetcOut: TFormatEtc): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    function TBitmapOle.SetData(const formatetc: TFormatEtc; var medium: TStgMedium; fRelease: BOOL): HResult; stdcall;
    begin
      FStgm := medium;
      FFmEtc := formatetc;
      Result := S_OK;
    end;
    
    function TBitmapOle.EnumFormatEtc(dwDirection: Longint; out enumFormatEtc: IEnumFormatEtc): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    function TBitmapOle.DAdvise(const formatetc: TFormatEtc; advf: Longint; const advSink: IAdviseSink; out dwConnection: Longint): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    function TBitmapOle.DUnadvise(dwConnection: Longint): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    function TBitmapOle.EnumDAdvise(out enumAdvise: IEnumStatData): HResult; stdcall;
    begin
      Result := E_NOTIMPL;
    end;
    
    procedure TBitmapOle.GetOleObject(OleSite: IOleClientSite; Storage: IStorage; var OleObject: IOleObject);
    begin
      OleCheck(OleCreateStaticFromData(Self, IID_IOleObject, OLERENDER_FORMAT, @FFmEtc, OleSite, Storage, OleObject));
    end;
    
    procedure TBitmapOle.SetBitmap(hBitmap: hBitmap);
    var
      Stgm: TStgMedium;
      FmEtc: TFormatEtc;
    begin
      Stgm.tymed := TYMED_GDI;                   // Storage medium = HBITMAP handle
      Stgm.hBitmap := hBitmap;
      Stgm.unkForRelease := nil;
    
      FmEtc.cfFormat := CF_BITMAP;               // Clipboard format = CF_BITMAP
      FmEtc.ptd := nil;                          // Target Device = Screen
      FmEtc.dwAspect := DVASPECT_CONTENT;        // Level of detail = Full content
      FmEtc.lindex := -1;                        // Index = Not applicaple
      FmEtc.tymed := TYMED_GDI;                  // Storage medium = HBITMAP handle
    
      SetData(FmEtc, Stgm, True);
    end;
    
    function InsertBitmap(hRichEdit: THandle; const FileName: string): Boolean;
    var
      ReOle: IRichEditOle;
      OleSite: IOleClientSite;
      Storage: IStorage;
      LockBytes: ILockBytes;
      OleObject: IOleObject;
      ReObj: TReObject;
      TempOle: IUnknown;
      FormatEtc: TFormatEtc;
    begin
      ReOle := GetRichEditOle(hRichEdit);
      Assert(ReOle <> nil, 'RichEditOle is null!');
    
      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!');
    
      OleCheck(OleCreateFromFile(GUID_NULL, PWideChar(WideString(FileName)), 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);
      ReObj.cbStruct := Sizeof(ReObj);
      OleCheck(OleObject.GetUserClassID(ReObj.clsid));
      ReObj.cp := REO_CP_SELECTION;
      ReObj.dvaspect := DVASPECT_CONTENT;
      ReObj.poleobj := OleObject;
      ReObj.polesite := OleSite;
      ReObj.pstg := Storage;
      ReObj.dwUser := 0;
      ReObj.sizel.cx := 0;
      ReObj.sizel.cy := 0;
    
      ReOle.InsertObject(ReObj);
      Result := True;
    end;
    
    function InsertBitmap(hRichEdit: THandle; Bitmap: TBitmap): Boolean;
    var
      ReOle: IRichEditOle;
      BitmapOle: TBitmapOle;
      OleSite: IOleClientSite;
      Storage: IStorage;
      LockBytes: ILockBytes;
      OleObject: IOleObject;
      ReObj: TReObject;
    begin
      ReOle := GetRichEditOle(hRichEdit);
      Assert(ReOle <> nil, 'RichEditOle is null!');
      BitmapOle := TBitmapOle.Create;
      try
        BitmapOle.SetBitmap(GetImage(Bitmap));
        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!');
    
        BitmapOle.GetOleObject(OleSite, Storage, OleObject);
        OleCheck(OleSetContainedObject(OleObject, True));
    
        FillChar(ReObj, Sizeof(ReObj), 0);
        ReObj.cbStruct := Sizeof(ReObj);
        OleCheck(OleObject.GetUserClassID(ReObj.clsid));
        ReObj.cp := REO_CP_SELECTION;
        ReObj.dvaspect := DVASPECT_CONTENT;
        ReObj.poleobj := OleObject;
        ReObj.polesite := OleSite;
        ReObj.pstg := Storage;
    
        ReOle.InsertObject(ReObj);
        Result := True;
      finally
        BitmapOle.Free;
      end;
    end;
    
    function InsertGif(hRichEdit: THandle; const FileName: string): Boolean;
    var
      ReOle: IRichEditOle;
      OleSite: IOleClientSite;
      Storage: IStorage;
      LockBytes: ILockBytes;
      OleObject: IOleObject;
      ReObj: TReObject;
      Animator: IGifAnimator;
    begin
      ReOle := GetRichEditOle(hRichEdit);
      Assert(ReOle <> nil, 'RichEditOle is null!');
      Assert(FileName <> '', 'FileName is null!');
    
      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!');
    
      Animator := IUnknown(CreateComObject(CLASS_GifAnimator)) as IGifAnimator;
      Animator.LoadFromFile(PWideChar(WideString(FileName)));
      OleCheck(Animator.QueryInterface(IID_IOleObject, OleObject));
    
      OleCheck(OleSetContainedObject(OleObject, True));
      FillChar(ReObj, Sizeof(ReObj), 0);
      ReObj.cbStruct := Sizeof(ReObj);
      OleCheck(OleObject.GetUserClassID(ReObj.clsid));
      ReObj.cp := REO_CP_SELECTION;
      ReObj.dvaspect := DVASPECT_CONTENT;
      ReObj.dwFlags := REO_STATIC or REO_BELOWBASELINE;
      ReObj.dwUser := 0;
      ReObj.poleobj := OleObject;
      ReObj.polesite := OleSite;
      ReObj.pstg := Storage;
      ReObj.sizel.cx := 0;
      ReObj.sizel.cy := 0;
    
      ReOle.InsertObject(ReObj);
      Result := True;
    end;
    
    end.
    

      

  • 相关阅读:
    jquery+flask+keras+nsfw快速搭建一个简易鉴黄工具
    基于LSTM + keras 的诗歌生成器
    Bilateral Multi-Perspective Matching for Natural Language Sentences---读书笔记
    text matching(文本匹配) 相关资料总结
    redis实战---读书笔记
    effective java(第三版)---读书笔记
    深入理解java虚拟机---读书笔记
    这就是搜索引擎(核心技术讲解)---读书笔记
    google nmt 实验踩坑记录
    python打包到pypi小结
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/9929390.html
Copyright © 2011-2022 走看看