Page 1 of 1

Insert Bitmap to RichEdit

Posted: Tue Jun 19, 2007 10:15 am
by Nico
For save and load RTF with images, you need code of Srod!
http://www.purebasic.fr/english/viewtop ... mreadwrite

Reference source code:
http://support.microsoft.com/default.as ... -us;220844

Code: Select all

; Insert a Bitmap file in the Editor
; Version PureBasic 4.10

#STGM_SHARE_EXCLUSIVE=$00000010
#STGM_READWRITE = $00000002
#STGM_CREATE = $00001000
#REO_CP_SELECTION=$FFFFFFFF
#REO_RESIZABLE=1
#REO_BELOWBASELINE=2
#OLERENDER_DRAW=1

Global RichEditOleObject.IRichEditOle
Global lpStorage.IStorage,lpObject.IOleObject,lpClientSite.IOleClientSite

Prototype.l CreateFromFile(a.l, FileName.p-bstr, b.l, c.l, d.l, e.l, f.l, g.l)

Procedure.l FileToOLE(FileName.s,Rich_Edit_ID.l)
 
  SendMessage_(GadgetID(Rich_Edit_ID), #EM_GETOLEINTERFACE, 0, @RichEditOleObject.IRichEditOle)
 
  If RichEditOleObject
   
    lpLockBytes.ILockBytes
    cfFormat = 0
    lpFormatEtc.FORMATETC
    clsid.CLSID
   
    CopyMemory(?IID_NULL,@clsid,16)
   
    sc = CreateILockBytesOnHGlobal_(#Null, #True, @lpLockBytes)
    If sc = #S_OK
      sc =StgCreateDocfileOnILockBytes_(lpLockBytes,#STGM_SHARE_EXCLUSIVE|#STGM_CREATE|#STGM_READWRITE, 0, @lpStorage)
     
      If sc = #S_OK
        lpLockBytes\Release()
      Else
        ProcedureReturn #False
      EndIf
    Else
      ProcedureReturn #False
    EndIf
   
    ;// fill in FORMATETC struct
    lpFormatEtc\cfFormat = 0
    lpFormatEtc\ptd = #Null
    lpFormatEtc\dwAspect = #DVASPECT_CONTENT
    lpFormatEtc\lindex = -1
    lpFormatEtc\tymed = #TYMED_NULL
   
    ;// attempt To create the object
    RichEditOleObject\GetClientSite(@lpClientSite)
   
    If OpenLibrary(0, "ole32.dll")
      CreateFromFile.CreateFromFile = GetFunction(0, "OleCreateFromFile")   
      sc = CreateFromFile( clsid, FileName, ?IID_IUnknown, #OLERENDER_DRAW, lpFormatEtc, lpClientSite, lpStorage, @lpObject)
      CloseLibrary(0)
    EndIf
   
    Debug sc
    ; je devrais avoir 0 mais on a 48 ?
   
   
    ;// lpObject is currently an IUnknown, convert To IOleObject
    If lpObject<> #Null
      lpUnk.IUnknown = lpObject
      lpUnk\QueryInterface(?IID_IOleObject, @lpObject)
      lpUnk\Release()
       EndIf
     
       ;// all items are "contained" -- this makes our reference To this object
       ;//  weak -- which is needed For links To embedding silent update.
       OleSetContainedObject_(lpObject, #True)
     
       reobject.REOBJECT
       ZeroMemory_(@reobject, SizeOf(REOBJECT))
       reobject\cbStruct = SizeOf(REOBJECT)
     
       sc = lpObject\GetUserClassID(clsid.CLSID)
       Debug sc
     
       CopyMemory(@clsid,@reobject\clsid,16)
     
       reobject\cp = #REO_CP_SELECTION
       reobject\dvaspect = #DVASPECT_CONTENT
       reobject\dwFlags = #REO_RESIZABLE | #REO_BELOWBASELINE
       reobject\dwUser = 0
       reobject\poleobj = lpObject
     
       reobject\polesite = lpClientSite
     
       reobject\pstg = lpStorage
     
       reobject\sizel\cx=0
       reobject\sizel\cy=0
       
       RichEditOleObject\InsertObject(reobject)
       
       If lpObject
          lpObject\Release()
          lpObject = #Null
       EndIf
         
       If lpStorage
          lpStorage\Release()
          lpStorage = #Null
       EndIf
         
       If lpClientSite
          lpClientSite\Release()
          lpClientSite = #Null
       EndIf
      
       If RichEditOleObject
          RichEditOleObject\Release()
          RichEditOleObject = #Null
       EndIf
   
    ProcedureReturn #True
  EndIf
EndProcedure

Enumeration
  #GADGET_Editor
EndEnumeration

If OpenWindow(0, 0, 0, 500, 440, "RichEdit", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  CreateGadgetList(WindowID(0))
 
  EditorGadget(#GADGET_Editor, 10, 10, 480, 380)
  ButtonGadget(1, 10, 400, 200, 20, "Choose Bitmap File")
 
  Repeat
    Event = WaitWindowEvent()
    Select Event   
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            Select EventType()
              Case #PB_EventType_LeftClick
                FichierParDefaut$ = "C:\"
                Filtre$ = "Bitmap(*.bmp)|*.bmp"
                Filtre  = 0 
                Fichier$ = OpenFileRequester("Choose Bitmap File", FichierParDefaut$, Filtre$, Filtre)
                If Fichier$
                  Ret=FileToOLE(Fichier$,0)
                  If Ret=0
                    MessageRequester("Information", "Le chargement de l'image dans l'éditeur à échoué", 0)
                  EndIf
                Else
                  MessageRequester("Information", "La sélection a été annulée.", 0)
                EndIf
            EndSelect 
           
        EndSelect
    EndSelect
  Until Event = #PB_Event_CloseWindow
 
EndIf
End

DataSection
IID_IOleObject: ;"{00000112-0000-0000-C000-000000000046}"
Data.l $00000112
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46

IID_IUnknown:   ;"{00000000-0000-0000-C000-000000000046}"
Data.l $00000000
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
   
IID_NULL:   ;"{00000000-0000-0000-0000-000000000000}"
Data.l $00000000
Data.w $0000,$0000
Data.b $00,$00,$00,$00,$00,$00,$00,$09 
EndDataSection

Posted: Tue Jun 19, 2007 10:17 am
by Nico
For save and load RTF with images, you need code of Srod!
http://www.purebasic.fr/english/viewtop ... mreadwrite

Code: Select all

; Insert a Bitmap Clipboard in the Editor
; Version PureBasic 4.10

#STGM_SHARE_EXCLUSIVE=$00000010
#STGM_READWRITE = $00000002
#STGM_CREATE = $00001000 
#REO_CP_SELECTION=$FFFFFFFF
#REO_RESIZABLE=1
#REO_BELOWBASELINE=2
#OLERENDER_FORMAT=2

Global RichEditOleObject.IRichEditOle
Global lpStorage.IStorage,lpObject.IOleObject,lpClientSite.IOleClientSite,lpDataObject.IDataobject


Procedure.l Paste_Image(Rich_Edit_ID.l)
  
  SendMessage_(GadgetID(Rich_Edit_ID), #EM_GETOLEINTERFACE, 0, @RichEditOleObject.IRichEditOle)
  
  If RichEditOleObject
    
    lpLockBytes.ILockBytes
    cfFormat = 0
    lpFormatEtc.FORMATETC
    clsid.CLSID
    
    CopyMemory(?IID_NULL,@clsid,16)
    
    sc = CreateILockBytesOnHGlobal_(#Null, #True, @lpLockBytes)
    If sc = #S_OK
      sc =StgCreateDocfileOnILockBytes_(lpLockBytes,#STGM_SHARE_EXCLUSIVE|#STGM_CREATE|#STGM_READWRITE, 0, @lpStorage)
      
      If sc = #S_OK
        lpLockBytes\Release()
      Else
        ProcedureReturn #False 
      EndIf 
    Else
      ProcedureReturn #False 
    EndIf 
    
    ; On récupère un Handle Bitmap OLE
    OleGetClipboard_(@lpDataObject)  
    lpFormatEtc\cfFormat = #CF_BITMAP
    lpFormatEtc\ptd = #Null
    lpFormatEtc\dwAspect = #DVASPECT_CONTENT
    lpFormatEtc\lindex = -1
    lpFormatEtc\tymed = #TYMED_GDI
    
    ;// attempt To create the object
    RichEditOleObject\GetClientSite(@lpClientSite)
    
    sc = OleCreateStaticFromData_(lpDataObject, ?IID_IOleObject, #OLERENDER_FORMAT, lpFormatEtc, lpClientSite, lpStorage, @lpObject)
    
    If sc = #S_OK
      
      ;// all items are "contained" -- this makes our reference To this object
      ;//  weak -- which is needed For links To embedding silent update.
      OleSetContainedObject_(lpObject, #True)
      
      reobject.REOBJECT
      ZeroMemory_(@reobject, SizeOf(REOBJECT))
      reobject\cbStruct = SizeOf(REOBJECT)
      
      sc = lpObject\GetUserClassID(clsid.CLSID)
      Debug sc
      
      CopyMemory(@clsid,@reobject\clsid,16)
    	
      reobject\cp = #REO_CP_SELECTION
      reobject\dvaspect = #DVASPECT_CONTENT
      reobject\dwFlags = #REO_RESIZABLE | #REO_BELOWBASELINE
      reobject\dwUser = 0
      reobject\poleobj = lpObject
      reobject\polesite = lpClientSite
      reobject\pstg = lpStorage
      reobject\sizel\cx=0
      reobject\sizel\cy=0
      
      RichEditOleObject\InsertObject(reobject)
      
      If lpDataObject
        lpDataObject\Release()
        lpDataObject = #Null
      EndIf 
      
      If lpObject
        lpObject\Release()
        lpObject = #Null
      EndIf 
      
      If lpStorage
        lpStorage\Release()
        lpStorage = #Null
      EndIf 
      
      If lpClientSite
        lpClientSite\Release()
        lpClientSite = #Null
      EndIf 
      
      If RichEditOleObject
        RichEditOleObject\Release()
        RichEditOleObject = #Null
      EndIf
      
      ProcedureReturn #True 
    EndIf 
    
    ProcedureReturn #False
  EndIf 
EndProcedure 

Enumeration
  #GADGET_Editor 
EndEnumeration

If OpenWindow(0, 0, 0, 500, 440, "RichEdit", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  CreateGadgetList(WindowID(0))
  
  EditorGadget(#GADGET_Editor, 10, 10, 480, 380)
  ButtonGadget(1, 10, 400, 200, 20, "Paste my Image")
  
  Repeat
    Event = WindowEvent()
    Select Event   
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            Select EventType()
              Case #PB_EventType_LeftClick
                If CreateImage(0,100,100)
                  StartDrawing(ImageOutput(0))
                  Box(0,0,100,100,RGB(0,0,255))
                  Circle(50,50,20,RGB(255,0,0))
                  StopDrawing()
                EndIf
                SetClipboardImage(0)
                
                Ret=Paste_Image(0)
                
            EndSelect  
            
        EndSelect
    EndSelect 
  Until Event = #PB_Event_CloseWindow
  
EndIf
End

DataSection
IID_IOleObject: ;"{00000112-0000-0000-C000-000000000046}"
Data.l $00000112
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46

IID_IUnknown:   ;"{00000000-0000-0000-C000-000000000046}"
Data.l $00000000
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46  
    
IID_NULL:   ;"{00000000-0000-0000-0000-000000000000}"
Data.l $00000000
Data.w $0000,$0000
Data.b $00,$00,$00,$00,$00,$00,$00,$00  
EndDataSection

Posted: Tue Jun 19, 2007 12:24 pm
by Nico
An example avec the code of Srod for load and save a file with image and move the image inside the editor!

Code: Select all

; Insérer une image Bitmap dans un éditeur à partir d'un fichier
; Version PureBasic 4.10

#STGM_SHARE_EXCLUSIVE=$00000010
#STGM_READWRITE = $00000002
#STGM_CREATE = $00001000
#REO_CP_SELECTION=$FFFFFFFF
#REO_RESIZABLE=1
#REO_BELOWBASELINE=2
#OLERENDER_DRAW=1

Global RichEditOleObject.IRichEditOle
Global lpStorage.IStorage,lpObject.IOleObject,lpClientSite.IOleClientSite

Prototype.l CreateFromFile(a.l, FileName.p-bstr, b.l, c.l, d.l, e.l, f.l, g.l)

Declare.l StreamDataCallback(dwCookie, pbBuff, cb, pcb)
Declare.l StreamFileInCallback(dwCookie, pbBuff, cb, pcb)
Declare.l StreamFileOutCallback(dwCookie, pbBuff, cb, pcb)

Structure RichEditOle
  *pIntf.l
  Refcount.l
EndStructure


;The following variable forms the IRichEditOleCallback interface for a rich edit control.
Global NewList RichComObject.RichEditOle()
;The following variable points to the rtf stream when including rtf files.
Global prtf


;-*****USER FUNCTIONS***************************************************************************


;***********************************************************************************************
;The following procedure includes an rtf file from a memory stream.
;Include the file using Include Binary etc.
;Returns zero if no error encountered.
;***********************************************************************************************
Procedure.l CatchRTF(gadget, datastart, dataend, replaceall=0)
  Protected edstr.EDITSTREAM
  prtf = datastart
  edstr\dwCookie = dataend
  edstr\dwError = 0
  edstr\pfnCallback = @StreamDataCallback()
  SendMessage_(GadgetID(gadget), #EM_STREAMIN, #SF_RTF|replaceall, edstr)
  ProcedureReturn edstr\dwError
EndProcedure
;The following is called repeatedly by Windows to stream data into an editor gadget.
Procedure.l StreamDataCallback(dwCookie, pbBuff, cb, pcb)
  Protected Result
  Result = 0
  If prtf>=dwCookie
    cb = 0
    Result = 1
  ElseIf prtf+cb>=dwCookie
    cb = dwCookie-prtf
  EndIf
  CopyMemory(prtf, pbBuff, cb)
  prtf+cb
  PokeL(pcb, cb)
  ProcedureReturn Result
EndProcedure


;***********************************************************************************************
;The following procedure loads an rtf file into an editor gadget.
;Returns zero if no error encountered.
;***********************************************************************************************
Procedure.l LoadRTF(gadget, FileName.s, replaceall=0)
  Protected edstr.EDITSTREAM
  edstr\dwCookie = ReadFile(#PB_Any, FileName)
  If edstr\dwCookie
    edstr\dwError = 0
    edstr\pfnCallback = @StreamFileInCallback()
    SendMessage_(GadgetID(gadget), #EM_STREAMIN, #SF_RTF|replaceall, edstr)
    CloseFile(edstr\dwCookie)
    ProcedureReturn edstr\dwError
  Else
    ProcedureReturn 1
  EndIf
EndProcedure
;The following is called repeatedly by Windows to stream data into an editor gadget from an external file.
Procedure.l StreamFileInCallback(dwCookie, pbBuff, cb, pcb)
  Protected Result, length
  Result=0
  length=ReadData(dwCookie, pbBuff, cb)
  PokeL(pcb, length)
  If length = 0
    Result = 1
  EndIf
  ProcedureReturn Result
EndProcedure


;***********************************************************************************************
;The following procedure saves the rtf content of an editor gadget to an external file.
;Returns zero if no error encountered.
;***********************************************************************************************
Procedure.l SaveRTF(gadget, FileName.s)
  Protected edstr.EDITSTREAM
  edstr\dwCookie = CreateFile(#PB_Any, FileName)
  If edstr\dwCookie
    edstr\dwError = 0
    edstr\pfnCallback = @StreamFileOutCallback()
    SendMessage_(GadgetID(gadget), #EM_STREAMOUT, #SF_RTF, edstr)
    CloseFile(edstr\dwCookie)
    ProcedureReturn edstr\dwError
  Else
    ProcedureReturn 1
  EndIf
EndProcedure
;The following is called repeatedly by Windows to stream data from an editor gadget to an external file.
Procedure.l StreamFileOutCallback(dwCookie, pbBuff, cb, pcb)
  Protected Result, length
  Result=0
  WriteData(dwCookie, pbBuff, cb)
  PokeL(pcb, cb)
  If cb = 0
    Result = 1
  EndIf
  ProcedureReturn Result
EndProcedure


;***********************************************************************************************
;Implementation procedures for OLE. Most are not actually used but are still needed.
;***********************************************************************************************
;***********************************************************************************************
;Set up the com interface for our rich edit control.
;***********************************************************************************************
Procedure.l RichEdit_SetInterface(hwnd)
Debug 1
  ;  If RichComObject\Refcount=0
  AddElement(RichComObject())
  RichComObject()\pIntf = ?VTable
  SendMessage_(hwnd, #EM_SETOLECALLBACK, 0, RichComObject())
  ;  EndIf
EndProcedure

Procedure.l RichEdit_QueryInterface(*pObject.RichEditOle, REFIID, ppvObj)
Debug 2
  ppvObj=0
  If CompareMemory(REFIID,?IID_IRichEditOleCallback,16)
    ppvObj=*pObject\pIntf
    ProcedureReturn #S_OK
  Else
    ProcedureReturn #E_NOINTERFACE
  EndIf
 
EndProcedure

Procedure.l RichEdit_AddRef(*pObject.RichEditOle)
Debug 3
  *pObject\Refcount+1
  ProcedureReturn *pObject\Refcount
EndProcedure

Procedure.l RichEdit_Release(*pObject.RichEditOle)
Debug 4
  *pObject\Refcount-1
  If *pObject\Refcount > 0
    ProcedureReturn *pObject\Refcount
  Else
    ;Remove entry in the linked list.
    ForEach RichComObject()
      If RichComObject()=*pObject
        DeleteElement(RichComObject()) : Break
      EndIf
    Next
    *pObject=0
  EndIf
EndProcedure
 
Procedure.l RichEdit_GetInPlaceContext(*pObject.RichEditOle, lplpFrame, lplpDoc, lpFrameInfo)
Debug 5
  Debug 1
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_ShowContainerUI(*pObject.RichEditOle, fShow)
Debug 6
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_QueryInsertObject(*pObject.RichEditOle, lpclsid, lpstg, cp)
Debug 7
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_DeleteObject(*pObject.RichEditOle, lpoleobj)
Debug 8
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_QueryAcceptData(*pObject.RichEditOle, lpdataobj, lpcfFormat, reco, fReally, hMetaPict)
Debug 9
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_ContextSensitiveHelp(*pObject.RichEditOle, fEnterMode)
Debug 10
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_GetClipboardData(*pObject.RichEditOle, lpchrg, reco, lplpdataobj)
Debug 11
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_GetDragDropEffect(*pObject.RichEditOle, fDrag, grfKeyState, pdwEffect)
Debug 12
  ;If  fDrag=0
  ;PokeL(pdwEffect,0) ;Uncomment this to prevent dropping to the editor gadget.
  ProcedureReturn #S_OK
EndProcedure

Procedure.l RichEdit_GetContextMenu(*pObject.RichEditOle, seltype.w, lpoleobj, lpchrg, lphmenu)
Debug 13
  ProcedureReturn #S_OK
EndProcedure


;The following function does the main work!
Procedure.l RichEdit_GetNewStorage(*pObject.RichEditOle, lplpstg)
Debug 14
  Protected sc, lpLockBytes.ILockBytes
  ;Attempt to create a byte array object which acts as the 'foundation' for the upcoming compound file.
  sc=CreateILockBytesOnHGlobal_(#Null, #True, @lpLockBytes)
  If sc ;This means that the allocation failed.
    ProcedureReturn sc
  EndIf
  ;Allocation succeeded so we now attempt to create a compound file storage object.
  sc=StgCreateDocfileOnILockBytes_(lpLockBytes, #STGM_SHARE_EXCLUSIVE|#STGM_READWRITE|#STGM_CREATE, 0, lplpstg)
  If sc ;This means that the allocation failed.
    lpLockBytes\Release()
    ProcedureReturn sc
  EndIf
EndProcedure
;***********************************************************************************************

DataSection
VTable:
Data.l @RichEdit_QueryInterface(), @RichEdit_AddRef(), @RichEdit_Release(), @RichEdit_GetNewStorage()
Data.l @RichEdit_GetInPlaceContext(), @RichEdit_ShowContainerUI(), @RichEdit_QueryInsertObject()
Data.l @RichEdit_DeleteObject(), @RichEdit_QueryAcceptData(), @RichEdit_ContextSensitiveHelp(), @RichEdit_GetClipboardData()
Data.l @RichEdit_GetDragDropEffect(), @RichEdit_GetContextMenu()

IID_IRichEditOle: ;"0x00020D00, 0, 0, 0xC0,0,0,0,0,0,0,0x46)"
Data.l $00020D00
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46 

IID_IRichEditOleCallback: ;" 0x00020D03, 0, 0, 0xC0,0,0,0,0,0,0,0x46"
Data.l $00020D03
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
EndDataSection




Procedure.l FileToOLE(FileName.s,Rich_Edit_ID.l)
 
  SendMessage_(GadgetID(Rich_Edit_ID), #EM_GETOLEINTERFACE, 0, @RichEditOleObject.IRichEditOle)
 
  If RichEditOleObject
   
    lpLockBytes.ILockBytes
    cfFormat = 0
    lpFormatEtc.FORMATETC
    clsid.CLSID
   
    CopyMemory(?IID_NULL,@clsid,16)
   
    sc = CreateILockBytesOnHGlobal_(#Null, #True, @lpLockBytes)
    If sc = #S_OK
      sc =StgCreateDocfileOnILockBytes_(lpLockBytes,#STGM_SHARE_EXCLUSIVE|#STGM_CREATE|#STGM_READWRITE, 0, @lpStorage)
     
      If sc = #S_OK
        lpLockBytes\Release()
      Else
        ProcedureReturn #False
      EndIf
    Else
      ProcedureReturn #False
    EndIf
   
    ;// fill in FORMATETC struct
    lpFormatEtc\cfFormat = 0
    lpFormatEtc\ptd = #Null
    lpFormatEtc\dwAspect = #DVASPECT_CONTENT
    lpFormatEtc\lindex = -1
    lpFormatEtc\tymed = #TYMED_NULL
   
    ;// attempt To create the object
    RichEditOleObject\GetClientSite(@lpClientSite)
   
    If OpenLibrary(0, "ole32.dll")
      CreateFromFile.CreateFromFile = GetFunction(0, "OleCreateFromFile")   
      sc = CreateFromFile( clsid, FileName, ?IID_IUnknown, #OLERENDER_DRAW, lpFormatEtc, lpClientSite, lpStorage, @lpObject)
      CloseLibrary(0)
    EndIf
   
    Debug sc
    ; je devrais avoir 0 mais on a 48 ?
   
   
    ;// lpObject is currently an IUnknown, convert To IOleObject
    If lpObject<> #Null
      lpUnk.IUnknown = lpObject
      lpUnk\QueryInterface(?IID_IOleObject, @lpObject)
      lpUnk\Release()
    EndIf
   
    ;// all items are "contained" -- this makes our reference To this object
    ;//  weak -- which is needed For links To embedding silent update.
    OleSetContainedObject_(lpObject, #True)
   
    reobject.REOBJECT
    ZeroMemory_(@reobject, SizeOf(REOBJECT))
    reobject\cbStruct = SizeOf(REOBJECT)
   
    sc = lpObject\GetUserClassID(clsid.CLSID)
    Debug sc
   
    CopyMemory(@clsid,@reobject\clsid,16)
   
    reobject\cp = #REO_CP_SELECTION
    reobject\dvaspect = #DVASPECT_CONTENT
    reobject\dwFlags = #REO_RESIZABLE | #REO_BELOWBASELINE
    reobject\dwUser = 0
    reobject\poleobj = lpObject
   
    reobject\polesite = lpClientSite
   
    reobject\pstg = lpStorage
   
    reobject\sizel\cx=0
    reobject\sizel\cy=0
   
    RichEditOleObject\InsertObject(reobject)
   
    If lpObject
      lpObject\Release()
      lpObject = #Null
    EndIf
       
    If lpStorage
      lpStorage\Release()
      lpStorage = #Null
    EndIf
       
    If lpClientSite
      lpClientSite\Release()
      lpClientSite = #Null
    EndIf
   
    If RichEditOleObject
      RichEditOleObject\Release()
      RichEditOleObject = #Null
    EndIf
   
    ProcedureReturn #True
  EndIf
EndProcedure

Enumeration
  #GADGET_Editor
EndEnumeration


If OpenWindow(0, 0, 0, 500, 440, "RichEdit", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  CreateGadgetList(WindowID(0))
 
  EditorGadget(#GADGET_Editor, 10, 10, 480, 380)
  RichEdit_SetInterface(GadgetID(#GADGET_Editor))
 
  ButtonGadget(1, 10, 400, 120, 20, "Ouvrir un fichier Image")
  ButtonGadget(2, 140, 400, 120, 20, "Save the file")
  ButtonGadget(3, 280, 400, 120, 20, "Open a file")

 
  Repeat
    Event = WaitWindowEvent()
    Select Event   
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            Select EventType()
              Case #PB_EventType_LeftClick
                  FichierParDefaut$ = "C:\"
                  Filtre$ = "Bitmap(*.bmp)|*.bmp"
                  Filtre  = 0 
                  Fichier$ = OpenFileRequester("Choisissez un fichier à charger", FichierParDefaut$, Filtre$, Filtre)
                  If Fichier$
                    Ret=FileToOLE(Fichier$,#GADGET_Editor)
                    If Ret=0
                      MessageRequester("Information", "Le chargement de l'image dans l'éditeur à échoué", 0)
                    EndIf
                  Else
                    MessageRequester("Information", "La sélection a été annulée.", 0)
                  EndIf
            EndSelect
             
         Case 2
            Select EventType()
              Case #PB_EventType_LeftClick
                  FichierParDefaut$ = "C:\"
                  Filtre$ = "Fichier texte(*.rtf)|*.rtf"
                  Filtre  = 0 
                  Fichier$ = SaveFileRequester("Choisissez un fichier à sauvegarder", FichierParDefaut$, Filtre$, Filtre)
                  If Fichier$
                      SaveRTF(#GADGET_Editor,Fichier$)
                  Else
                    MessageRequester("Information", "La sélection a été annulée.", 0)
                  EndIf
            EndSelect
           
         Case 3
            Select EventType()
              Case #PB_EventType_LeftClick
                  FichierParDefaut$ = "C:\"
                  Filtre$ = "Fichier texte(*.rtf)|*.rtf"
                  Filtre  = 0 
                  Fichier$ = OpenFileRequester("Choisissez un fichier à charger", FichierParDefaut$, Filtre$, Filtre)
                  If Fichier$
                    LoadRTF(#GADGET_Editor, "c:\essai.rtf")
                  Else
                    MessageRequester("Information", "La sélection a été annulée.", 0)
                  EndIf

            EndSelect
        EndSelect
 
    EndSelect
  Until Event = #PB_Event_CloseWindow
 
EndIf
End

DataSection
IID_IOleObject: ;"{00000112-0000-0000-C000-000000000046}"
Data.l $00000112
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46

IID_IUnknown:   ;"{00000000-0000-0000-C000-000000000046}"
Data.l $00000000
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
   
IID_NULL:   ;"{00000000-0000-0000-0000-000000000000}"
Data.l $00000000
Data.w $0000,$0000
Data.b $00,$00,$00,$00,$00,$00,$00,$00 
EndDataSection

Posted: Tue Jun 19, 2007 12:50 pm
by ts-soft
Thanks for the great code,
but i wait for the drop example with image on editorgadget :wink:

Posted: Thu Jun 28, 2007 7:04 pm
by Nico
You can drop image inside the Editorgadget !!!

Posted: Sat Jun 30, 2007 10:55 am
by Nico

Code: Select all

;-------------------------------------------------------------------------
; Cette source est une traduction d'un code qui provient du Site CodeGuru
; http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
; Auteur original: Hani Atassi
;-------------------------------------------------------------------------
; Insert a Bitmap Handle into Editor
; No clipboard, No query file in the disk
; Version PureBasic 4.10
;-------------------------------------------------------------------------
; Ce code crée sa propre interface iDataObject afin de pouvoir réaliser
; un appel à la fonction: OleCreateStaticFromData
;-------------------------------------------------------------------------

Structure iData
  *pIntf.IDataobject
  Refcount.l
  m_stgmed.STGMEDIUM
  m_fromat.FORMATETC
EndStructure

Global NewList IDataObject.iData()

#STGM_SHARE_EXCLUSIVE=$00000010
#STGM_READWRITE = $00000002
#STGM_CREATE = $00001000
#REO_CP_SELECTION=$FFFFFFFF
#REO_RESIZABLE=1
#REO_BELOWBASELINE=2
#OLERENDER_FORMAT=2

Procedure dataobject_AddRef(*dataobject.iData)
  Debug "AddRef"
  *dataobject\Refcount=*dataobject\Refcount+1
  ProcedureReturn *dataobject\Refcount
EndProcedure

Procedure dataobject_Release(*dataobject.iData)
  *dataobject\Refcount=*dataobject\Refcount-1
  If *dataobjectRefcount > 0
    ProcedureReturn *dataobject\Refcount
  Else
    ForEach IDataObject()
      If IDataObject()=*dataobject
        Debug "Release"
        DeleteElement(IDataObject()) : Break
      EndIf
    Next
    *dataobject=0
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure dataobject_QueryInterface(*dataobject.IDataobject, iid, *ppvObject.Long)
  If CompareMemory(iid, ?IID_IUnknown, 16)=1 Or CompareMemory(iid, ?IID_IDataObject, 16)=1
    Debug "QueryInterface"
    *ppvObject\l = *dataobject
    *dataobject\AddRef()
    ProcedureReturn #S_OK
  Else
    *ppvObject=0
    ProcedureReturn #E_NOINTERFACE
  EndIf
EndProcedure
   
Procedure dataobject_GetData(*dataobject.iData,*pformatetcIn.FORMATETC, *pmedium.STGMEDIUM)
  Protected hbitmap.l
  If *pformatetcIn\tymed=*dataobject\m_fromat\tymed
    If *pformatetcIn\cfFormat=*dataobject\m_fromat\cfFormat
      Debug "GetData"
      hbitmap = OleDuplicateData_(*dataobject\m_stgmed\hBitmap, #CF_BITMAP, #Null)
      *pmedium\tymed = *dataobject\m_stgmed\tymed
      *pmedium\hBitmap = hbitmap
      *pmedium\pUnkForRelease = *dataobject\m_stgmed\pUnkForRelease
    EndIf
  EndIf
  ProcedureReturn #S_OK
EndProcedure

Procedure dataobject_GetDataHere(*dataobject, *pformatetc, *pmedium )
  Debug "GetDataHere"
  ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure dataobject_QueryGetData(*dataobject, *pformatetc )
  Debug "QueryGetData"
  ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure dataobject_GetCanonicalFormatEtc(*dataobject, *pformatectIn ,*pformatetcOut )
  Debug "GetCanonicalFormatEtc"
  ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure dataobject_SetData(*dataobject.iData, *pformatetc.FORMATETC , *pmedium.STGMEDIUM , fRelease )
  Debug "SetData"
  CopyMemory(*pformatetc,*dataobject\m_fromat,SizeOf(FORMATETC))
  CopyMemory(*pmedium,*dataobject\m_stgmed,SizeOf(STGMEDIUM))
 
  ProcedureReturn #S_OK
EndProcedure

Procedure dataobject_EnumFormatEtc(*dataobject, dwDirection , *ppenumFormatEtc )
  Debug "EnumFormatEtc"
  ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure dataobject_DAdvise(*dataobject,*pformatetc, advf, *pAdvSink, *pdwConnection)
  Debug "DAdvise"
  ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure dataobject_DUnadvise(*dataobject, dwConnection)
  Debug "DUnadvise"
  ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure dataobject_EnumDAdvise(*dataobject, *ppenumAdvise)
  Debug "EnumDAdvise"
  ProcedureReturn #E_NOTIMPL
EndProcedure
   
Procedure.l Paste_Image(hBitmap.l,Rich_Edit_ID.l)
  Protected Ret.l,sc.l,pods.IDataobject,stgm.STGMEDIUM ,fm.FORMATETC
 
  hBitmap=CopyImage_(hBitmap,#IMAGE_BITMAP,0,0,#LR_COPYRETURNORG)
  If hBitmap
  
    SendMessage_(GadgetID(Rich_Edit_ID), #EM_GETOLEINTERFACE, 0, @RichEditOleObject.IRichEditOle)
   
    If RichEditOleObject
      AddElement(IDataObject())
      IDataObject()\pIntf=?VTable_IDataObject
      pods.IDataobject=IDataObject()
  
  
      stgm\tymed = #TYMED_GDI            ;         // Storage medium = HBITMAP handle     
      stgm\hBitmap = hBitmap             ;         // HBITMAP handle
      stgm\pUnkForRelease = #Null        ;         // Use ReleaseStgMedium
     
  
      fm\cfFormat = #CF_BITMAP           ;         // Clipboard format = CF_BITMAP
      fm\ptd = #Null                     ;         // Target Device = Screen
      fm\dwAspect = #DVASPECT_CONTENT    ;         // Level of detail = Full content
      fm\lindex = -1                     ;         // Index = Not applicaple
      fm\tymed = #TYMED_GDI              ;         // Storage medium = HBITMAP handle
     
     
      CopyMemory(?IID_IUnknown,@iid.IID,16)
      sc=pods\QueryInterface(iid.IID, @lpDataObject.IDataobject)
     
      sc=pods\SetData(@fm, @stgm, #True)
     
      sc = CreateILockBytesOnHGlobal_(#Null, #True, @lpLockBytes.ILockBytes)
      If sc = #S_OK
       
        sc =StgCreateDocfileOnILockBytes_(lpLockBytes,#STGM_SHARE_EXCLUSIVE|#STGM_CREATE|#STGM_READWRITE, 0, @lpStorage.IStorage)
        If sc = #S_OK
         
          sc =RichEditOleObject\GetClientSite(@lpClientSite.IOleClientSite)
          If sc = #S_OK
           
            sc = OleCreateStaticFromData_(lpDataObject, ?IID_IOleObject, #OLERENDER_FORMAT, IDataObject()\m_fromat, lpClientSite, lpStorage, @lpOleObject.IOleObject)
            If sc = #S_OK
             
              OleSetContainedObject_(lpOleObject, #True)
             
              reobject.REOBJECT
              ZeroMemory_(@reobject, SizeOf(REOBJECT))
              reobject\cbStruct = SizeOf(REOBJECT)
             
              sc = lpOleObject\GetUserClassID(@clsid.CLSID)
             
              CopyMemory(@clsid.CLSID,@reobject\clsid,16)
             
              reobject\cp = #REO_CP_SELECTION
              reobject\dvaspect = #DVASPECT_CONTENT
              reobject\dwFlags = #REO_RESIZABLE
              reobject\dwUser = 0
              reobject\poleobj = lpOleObject
              reobject\polesite = lpClientSite
              reobject\pstg = lpStorage
              reobject\sizel\cx=0
              reobject\sizel\cy=0
             
              Ret= RichEditOleObject\InsertObject(reobject)
            EndIf
          EndIf
        EndIf
      EndIf
     
      If lpLockBytes
        lpLockBytes\Release()
        lpLockBytes=0
      EndIf
     
      If lpDataObject
        lpDataObject\Release()
        lpDataObject = #Null
      EndIf
     
      If lpOleObject
        lpOleObject\Release()
        lpOleObject = #Null
      EndIf
     
      If lpStorage
        lpStorage\Release()
        lpStorage = #Null
      EndIf
     
      If lpClientSite
        lpClientSite\Release()
        lpClientSite = #Null
      EndIf
     
      If RichEditOleObject
        RichEditOleObject\Release()
        RichEditOleObject = #Null
      EndIf
    EndIf
    DeleteObject_(hBitmap)
  EndIf 
  ProcedureReturn Ret
EndProcedure

DataSection
VTable_IDataObject:
Data.l @dataobject_QueryInterface(), @dataobject_AddRef(), @dataobject_Release()
Data.l @dataobject_GetData(),@dataobject_GetDataHere(),@dataobject_QueryGetData()
Data.l @dataobject_GetCanonicalFormatEtc(),@dataobject_SetData(),@dataobject_EnumFormatEtc()
Data.l @dataobject_DAdvise(),@dataobject_DUnadvise(),@dataobject_EnumDAdvise()

IID_IDataObject:  ;{0000010e-0000-0000-C000-000000000046"}
Data.l $0000010E
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46

IID_IOleObject:   ;"{00000112-0000-0000-C000-000000000046}"
Data.l $00000112
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46

EndDataSection  
[Code Updated: Sun Jul 01]

Re: Insert Bitmap to RichEdit

Posted: Wed Aug 28, 2024 4:34 am
by Zapman
Thank you Nico
A simplified and updated version for PB 6.xx:

Code: Select all

;************************************************************************
;
;                    Insert Image in RichEdit Gadget
;
;                  Insert a Bitmap Handle into Editor
;               No clipboard, No query file in the disk
;
;************************************************************************
; Cette source est une traduction d'un code qui provient du Site CodeGuru
; http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
; Auteur original: Hani Atassi
; Adapté pour PB 4.1 par 'Nico', forum PureBasic
; Simplifié et adapté pour PB 6.1 par 'Zapman', forum PureBasic

;************************************************************************
; Ce code crée sa propre interface iDataObject afin de pouvoir réaliser
; un appel à la fonction: OleCreateStaticFromData
;************************************************************************

#STGM_SHARE_EXCLUSIVE=$00000010
#STGM_READWRITE = $00000002
#STGM_CREATE = $00001000
#REO_CP_SELECTION=$FFFFFFFF
#REO_RESIZABLE=1
#REO_BELOWBASELINE=2
#OLERENDER_FORMAT=2
;
Procedure.l InsertImageInREGadget(hBitmap, Rich_Edit_ID)
  ;
  Protected RichEditOleObject.IRichEditOle
  Protected          Ret.l
  Protected           sc
  Protected         stgm.STGMEDIUM
  Protected           fm.FORMATETC
  Protected  lpLockBytes.ILockBytes
  Protected    lpStorage.IStorage
  Protected  lpOleObject.IOleObject
  Protected lpClientSite.IOleClientSite
  Protected     reobject.REOBJECT
  ;
  Structure iData
    *pIntf.IDataobject
    m_stgmed.STGMEDIUM
    m_format.FORMATETC
  EndStructure
  ;
  Protected     mDataObj.idata
  ;
  hBitmap = CopyImage_(hBitmap, #IMAGE_BITMAP, 0, 0, #LR_COPYRETURNORG)
  If hBitmap
    SendMessage_(GadgetID(Rich_Edit_ID), #EM_GETOLEINTERFACE, 0, @RichEditOleObject)
   
    If RichEditOleObject
      
      mDataObj\pIntf = ?VTable_IDataObject
      
      mDataObj\m_stgmed\tymed = #TYMED_GDI            ;         // Storage medium = HBITMAP handle     
      mDataObj\m_stgmed\hBitmap = hBitmap             ;         // HBITMAP handle
      mDataObj\m_stgmed\pUnkForRelease = #Null        ;         // Use ReleaseStgMedium
  
      mDataObj\m_format\cfFormat = #CF_BITMAP         ;         // Clipboard format = CF_BITMAP
      mDataObj\m_format\ptd = #Null                   ;         // Target Device = Screen
      mDataObj\m_format\dwAspect = #DVASPECT_CONTENT  ;         // Level of detail = Full content
      mDataObj\m_format\lindex = -1                   ;         // Index = Not applicaple
      mDataObj\m_format\tymed = #TYMED_GDI            ;         // Storage medium = HBITMAP handle
      
      sc = CreateILockBytesOnHGlobal_(#Null, #True, @lpLockBytes)
      If sc = #S_OK
       
        sc = StgCreateDocfileOnILockBytes_(lpLockBytes,#STGM_SHARE_EXCLUSIVE|#STGM_CREATE|#STGM_READWRITE, 0, @lpStorage)
        If sc = #S_OK
         
          sc = RichEditOleObject\GetClientSite(@lpClientSite)
          If sc = #S_OK
            sc = OleCreateStaticFromData_(mDataObj, ?IID_IOleObject, #OLERENDER_FORMAT, mDataObj\m_format, lpClientSite, lpStorage, @lpOleObject)
            If sc = #S_OK
              ;
              OleSetContainedObject_(lpOleObject, #True)
             
              ZeroMemory_(@reobject, SizeOf(REOBJECT))
              reobject\cbStruct = SizeOf(REOBJECT)
             
              sc = lpOleObject\GetUserClassID(@reobject\clsid)
             
              reobject\cp       = #REO_CP_SELECTION
              reobject\dvaspect = #DVASPECT_CONTENT
              reobject\dwFlags  = #REO_RESIZABLE
              reobject\dwUser   = 0
              reobject\poleobj  = lpOleObject
              reobject\polesite = lpClientSite
              reobject\pstg     = lpStorage
              reobject\sizel\cx = 0
              reobject\sizel\cy = 0
             
              Ret = RichEditOleObject\InsertObject(reobject)
            EndIf
          EndIf
        EndIf
      EndIf
     
      If lpLockBytes
        lpLockBytes\Release()
      EndIf
     
      If lpOleObject
        lpOleObject\Release()
      EndIf
     
      If lpStorage
        lpStorage\Release()
      EndIf
     
      If lpClientSite
        lpClientSite\Release()
      EndIf
     
      If RichEditOleObject
        RichEditOleObject\Release()
      EndIf
    EndIf
    
    DeleteObject_(hBitmap)
    ;
  EndIf
  ;
  ProcedureReturn Ret
EndProcedure
;  
Procedure dataobject_GetData(*dataobject.iData, *pformatetcIn.FORMATETC, *pmedium.STGMEDIUM)
  Protected hbitmap
  If *pformatetcIn\tymed = *dataobject\m_format\tymed
    If *pformatetcIn\cfFormat = *dataobject\m_format\cfFormat
      hbitmap = OleDuplicateData_(*dataobject\m_stgmed\hBitmap, *dataobject\m_format\cfFormat, #Null)
      *pmedium\tymed = *dataobject\m_stgmed\tymed
      *pmedium\hBitmap = hbitmap
      *pmedium\pUnkForRelease = *dataobject\m_stgmed\pUnkForRelease
    EndIf
  EndIf
  ProcedureReturn #S_OK
EndProcedure
;
Procedure NotImplemented(a, b, c = 0, d = 0, e = 0)
  Debug "This procedure shoudn't be called."
  ProcedureReturn #E_NOTIMPL
EndProcedure
   

Enumeration
  #GADGET_Editor
EndEnumeration

If OpenWindow(0, 0, 0, 500, 240, "RichEdit", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
 
  EditorGadget(#GADGET_Editor, 10, 10, 480, 220)
  FichierParDefaut$ = "C:\"
  Filtre$ = "Bitmap|*.bmp|JPeg|*.jpg;*.jpeg" 
  Filtre  = 1 
  Fichier$ = OpenFileRequester("Choisissez un fichier à charger", FichierParDefaut$, Filtre$, Filtre)
  If Fichier$
    UseJPEGImageDecoder()
    MImage = LoadImage(#PB_Any, Fichier$)
    If MImage
      InsertImageInREGadget(ImageID(MImage),#GADGET_Editor)
    Else
      Debug "Image non chargée"
    EndIf
  EndIf
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
 
EndIf
End



DataSection
  
  VTable_IDataObject:
  Data.i @NotImplemented(), @NotImplemented(), @NotImplemented()
  Data.i @dataobject_GetData(),@NotImplemented(),@NotImplemented()
  Data.i @NotImplemented(),@NotImplemented(),@NotImplemented()
  Data.i @NotImplemented(),@NotImplemented(),@NotImplemented()
  
  IID_IOleObject:   ;"{00000112-0000-0000-C000-000000000046}"
  Data.l $00000112
  Data.w $0000,$0000
  Data.b $C0,$00,$00,$00,$00,$00,$00,$46

EndDataSection