May 21, 2024, 06:45:56 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


The RichEdit control

Started by Ionic Wind Support Team, January 24, 2006, 11:14:36 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ionic Wind Support Team

January 24, 2006, 11:14:36 PM Last Edit: February 23, 2006, 07:59:43 AM by Ionic Wizard
Finally finished with the RE control this evening.  Just to give you an idea what it's like to write an OLE callback interface and accept drag and drop objects in the RE control.

Not that you need to ever write it...since it's part of the control now ;)

This is something that was nearly impossible in IBasic Pro.  In Standard it was written in C++ and the conversion was relatively simple.

EDIT :This code is just for discussion and won't compile. If you want the entire file it is in the source archive


/*all of this needed to provide inplace OLE objects in a RichEdit control */

import int InterlockedIncrement(pointer pAddend);
import int InterlockedDecrement(pointer pAddend);
import int CreateILockBytesOnHGlobal (unsigned int hGlobal, int fDeleteOnRelease,
                                    pointer *pplkbyt);

import int StgCreateDocfileOnILockBytes(pointer plkbyt,
                    int grfMode,
                    int reserved,
                    pointer *ppstgOpen);


#typedef OLECHAR word
#define E_NOTIMPL 0x80004001u
#define E_NOINTERFACE 0x80004002u
#define S_OK 0
/* Storage instantiation modes */
#define STGM_DIRECT             0x00000000u
#define STGM_TRANSACTED         0x00010000u
#define STGM_SIMPLE             0x08000000u

#define STGM_READ               0x00000000u
#define STGM_WRITE              0x00000001u
#define STGM_READWRITE          0x00000002u

#define STGM_SHARE_DENY_NONE    0x00000040u
#define STGM_SHARE_DENY_READ    0x00000030u
#define STGM_SHARE_DENY_WRITE   0x00000020u
#define STGM_SHARE_EXCLUSIVE    0x00000010u

#define STGM_PRIORITY           0x00040000u
#define STGM_DELETEONRELEASE    0x04000000u
#define STGM_NOSCRATCH          0x00100000u

#define STGM_CREATE             0x00001000u
#define STGM_CONVERT            0x00020000u
#define STGM_FAILIFTHERE        0x00000000u

#define STGM_NOSNAPSHOT         0x00200000u

struct GUID,1
{
int data1;
word data2;
word data3;
byte data4[8];
}

EXTERN _IID_IUnknown as GUID;
EXTERN _IID_IRichEditOleCallback as GUID;

interface IUnknown
{
/*** IUnknown methods ***/
declare virtual QueryInterface(riid as POINTER, ppvObj as POINTER),int;
declare virtual AddRef(),int;
declare virtual Release(),int;
}

interface ILockBytes : IUnknown
{
//were only using the IUnknown method Release...so no need for the rest of the interface def.
}

interface IStorage : IUnknown
{
declare virtual CreateStream(
            /* [string][in] */ pointer pwcsName,
            /* [in] */ int grfMode,
            /* [in] */ int reserved1,
            /* [in] */ int reserved2,
            /* [out] */ pointer *ppstm),int;
       
declare virtual /* [local] */   OpenStream(
            /* [string][in] */  OLECHAR  *pwcsName,
            /* [unique][in] */ void  *reserved1,
            /* [in] */ int grfMode,
            /* [in] */ int reserved2,
            /* [out] */ pointer *ppstm),int;
       
declare virtual   CreateStorage(
            /* [string][in] */  OLECHAR  *pwcsName,
            /* [in] */ int grfMode,
            /* [in] */ int dwStgFmt,
            /* [in] */ int reserved2,
            /* [out] */ pointer *ppstg),int;
       
declare virtual   OpenStorage(
            /* [string][unique][in] */  OLECHAR *pwcsName,
            /* [unique][in] */ pointer pstgPriority,
            /* [in] */ int grfMode,
            /* [unique][in] */ pointer snbExclude,
            /* [in] */ int reserved,
            /* [out] */ pointer *ppstg),int;
       
declare virtual   CopyTo(
            /* [in] */ int ciidExclude,
            /* [size_is][unique][in] */  GUID  *rgiidExclude,
            /* [unique][in] */ pointer snbExclude,
            /* [unique][in] */ pointer pstgDest),int;
       
declare virtual   MoveElementTo(
            /* [string][in] */  OLECHAR  *pwcsName,
            /* [unique][in] */ pointer  pstgDest,
            /* [string][in] */  OLECHAR  *pwcsNewName,
            /* [in] */ int grfFlags),int;
       
declare virtual   Commit(
            /* [in] */ int grfCommitFlags),int;
       
declare virtual   Revert(),int;
       
declare virtual /* [local] */   EnumElements(
            /* [in] */ int reserved1,
            /* [size_is][unique][in] */ void  *reserved2,
            /* [in] */ int reserved3,
            /* [out] */ pointer *ppenum),int;
       
declare virtual   DestroyElement(
            /* [string][in] */  OLECHAR  *pwcsName),int;
       
declare virtual   RenameElement(
            /* [string][in] */  OLECHAR  *pwcsOldName,
            /* [string][in] */  OLECHAR  *pwcsNewName),int;
       
declare virtual   SetElementTimes(
            /* [string][in] */  OLECHAR  *pwcsName,
            /* [in] */  pointer pctime,
            /* [in] */  pointer patime,
            /* [in] */  pointer pmtime),int;
       
declare virtual   SetClass(
            /* [in] */ GUID *clsid),int;
       
declare virtual   SetStateBits(
            /* [in] */ int grfStateBits,
            /* [in] */ int grfMask),int;
       
declare virtual   Stat(
            /* [out] */ pointer pstatstg,
            /* [in] */ int grfStatFlag),int;
}

interface IRichEditOLECallback : IUnknown
{
    // *** IRichEditOleCallback methods ***
declare virtual GetNewStorage( pointer *lplpstg),int;
    declare virtual GetInPlaceContext( pointer *lplpFrame,pointer *lplpDoc,pointer lpFrameInfo),int;
declare virtual ShowContainerUI(int fShow),int;
declare virtual QueryInsertObject( pointer lpclsid, pointer lpstg,int cp),int;
declare virtual DeleteObject( pointer lpoleobj),int;
declare virtual QueryAcceptData( pointer lpdataobj,CLIPFORMAT *lpcfFormat, int reco,int fReally, unsigned int hMetaPict),int;
declare virtual ContextSensitiveHelp( int fEnterMode),int;
declare virtual GetClipboardData( CHARRANGE *lpchrg, int reco,pointer *lplpdataobj),int;
declare virtual GetDragDropEffect( int fDrag, int grfKeyState,pointer pdwEffect),int;
declare virtual GetContextMenu( WORD seltype, pointer lpoleobj,CHARRANGE *lpchrg,unsigned int *lphmenu),int;
}



class REOLECallBack : IRichEditOLECallback
{
declare REOLECallBack();
declare _REOLECallBack();

declare virtual QueryInterface(riid as POINTER, ppvObj as POINTER),int;
declare virtual AddRef(),int;
declare virtual Release(),int;

declare virtual GetNewStorage( pointer *lplpstg),int;
    declare virtual GetInPlaceContext( pointer *lplpFrame,pointer *lplpDoc,pointer lpFrameInfo),int;
declare virtual ShowContainerUI(int fShow),int;
declare virtual QueryInsertObject( pointer lpclsid, pointer lpstg,int cp),int;
declare virtual DeleteObject( pointer lpoleobj),int;
declare virtual QueryAcceptData( pointer lpdataobj,pointer lpcfFormat, int reco,int fReally, unsigned int hMetaPict),int;
declare virtual ContextSensitiveHelp( int fEnterMode),int;
declare virtual GetClipboardData( CHARRANGE *lpchrg, int reco,pointer *lplpdataobj),int;
declare virtual GetDragDropEffect( int fDrag, int grfKeyState,pointer pdwEffect),int;
declare virtual GetContextMenu( WORD seltype, pointer lpoleobj,CHARRANGE *lpchrg,unsigned int *lphmenu),int;


    int mRefCounter;
IStorage *fStorage;
int nItemcount;
}

REOLECallBack::REOLECallBack()
{
mRefCounter = 0;
}
REOLECallBack::_REOLECallBack()
{
}

REOLECallBack::QueryInterface(riid as POINTER, ppvObj as POINTER),int
{
if(CompGuid(*(GUID)riid,_IID_IUnknown) or CompGuid(*(GUID)riid,_IID_IRichEditOleCallback))
return S_OK;
return E_NOINTERFACE;
}
REOLECallBack::AddRef(),int
{
InterlockedIncrement(&mRefCounter); return mRefCounter;
}
REOLECallBack::Release(),int
{
if ( InterlockedDecrement(&mRefCounter) <= 0 )
{
delete this;
return 0;
}
return mRefCounter;
}

REOLECallBack::GetNewStorage( pointer *lplpstg),int
{
    // Initialize a Storage Object from a DocFile in memory
    ILockBytes *lpLockBytes = NULL;
    int sc  = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
    if (sc <> S_OK) return sc;
    sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, lplpstg);
    if (sc <> S_OK) lpLockBytes->Release();
    return sc;
}

REOLECallBack::GetInPlaceContext( pointer *lplpFrame,pointer *lplpDoc,pointer lpFrameInfo),int {return E_NOTIMPL;}
REOLECallBack::ShowContainerUI(int fShow),int {return E_NOTIMPL;}
REOLECallBack::QueryInsertObject( pointer lpclsid, pointer lpstg,int cp),int {return S_OK;}
REOLECallBack::DeleteObject( pointer lpoleobj),int {return E_NOTIMPL;}
REOLECallBack::QueryAcceptData( pointer lpdataobj,pointer lpcfFormat, int reco,int fReally, unsigned int hMetaPict),int {return E_NOTIMPL;}
REOLECallBack::ContextSensitiveHelp( int fEnterMode),int {return E_NOTIMPL;}
REOLECallBack::GetClipboardData( CHARRANGE *lpchrg, int reco,pointer *lplpdataobj),int {return E_NOTIMPL;}
REOLECallBack::GetDragDropEffect( int fDrag, int grfKeyState,pointer pdwEffect),int {return E_NOTIMPL;}
REOLECallBack::GetContextMenu( WORD seltype, pointer lpoleobj,CHARRANGE *lpchrg,unsigned int *lphmenu),int {return E_NOTIMPL;}

sub CompGuid(GUID g1,GUID g2),int
{
int x;
if g1.data1 = g2.data2
{
if g1.data2 = g2.data2
{
if g1.data3 = g2.data3
{
for x=0;x<8;x++
{
if g1.data4[x] <> g2.data4[x]
return 0;
}
return 1;
}
}
}
return 0;
}
Ionic Wind Support Team

LarryMc

Tried Rich Edit with an image.

If I load an image(jpg) into an image editor and then do a ctrl-c while in the editor; I can then run the rich edit demo and do a ctrl-v and the image will appear.

If I drag the image from explorer to the richedit control all I get is an image name inside a small rectangle with no image.

Is that how drag and drop is suppose to work? ???

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Yes.  The default drag and drop in Windows is to create a link.  Try holding down the CTRL key while dragging.
Ionic Wind Support Team

LarryMc

February 19, 2006, 01:33:19 PM #3 Last Edit: February 19, 2006, 01:48:16 PM by tlmccaughn
If I try to drag a bitmap with and w/o ctrl I get a distorted image and the name of the file(yes, it is a link)

If I try a tiff with and w/o ctrl I get the name of the file(yes, it is a link)


Using ctrl and dragging a jpg i get just the file name and it must be trying to open the editor because I get one of those "poor baby...tell MS all about it" error messages.

Is there some way to force it to act the way it does when you copy the image to the clipboard and then paste from there?

Or is the proper way to get what I want done:

ÂÃ,  ÂÃ,  button to insert image that calls following routine:
ÂÃ,  ÂÃ, 1. filerequest to pick image I want
ÂÃ,  ÂÃ, 2. load image as a bitmap
ÂÃ,  ÂÃ, 3. save bitmap to clipboard
ÂÃ,  ÂÃ, 4. copy clipboard to richedit
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Perhaps using PasteSpecial would do it.  Search MSDN.

I guess it depends on what your trying to do with the RE control in the first place ;)  Drag and drop works with OLE and objects.  Dragging from the shell interface, such as a file view of explorer, you are dragging just a file name around.

Ionic Wind Support Team

LarryMc

I really want to select a file using filerequest and have the selected image inserted in a Richedit control at the current location.  I want that image to appear full size(determined by stored image)  I DON'T want any link to the image or to be able to edit the image or anything like that from the richedit.

My wants are pretty simple(or should I say 'straight-forward').  Gettin' there is the trick! ;D
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Editing is part of the RE control functionality...so your stuck with the double click opening Paint (or whatever the default is).

Ionic Wind Support Team

Steven Picard

Quote from: tlmccaughn on February 19, 2006, 04:29:53 PM
I really want to select a file using filerequest and have the selected image inserted in a Richedit control at the current location.  I want that image to appear full size(determined by stored image)  I DON'T want any link to the image or to be able to edit the image or anything like that from the richedit.

My wants are pretty simple(or should I say 'straight-forward').  Gettin' there is the trick! ;D
You can copy the image to the clipboard and then paste it into the RichText document.  That should overcome your problem.  When that method is used it will not be considered an OLE object. 

Sorry I don't have sample code in Aurora for you but this is how I accomplished it in VB.

sapero

tlmccaughn, here's your solution with system IPicture class
#define RICHEDIT_1 1
#define BUTTON_2 2
#define BUTTON_3 3

#use "oleaut32.lib"

class dlg:CDialog
{
declare OnInitDialog(),int;
declare OnClose(),int;
declare OnControl(int nID, int nNotifyCode, unsigned int hControl),int;
declare OnSize(int nType,int cx,int cy),int;

declare InsertFile(string Path, CRichEdit *re1);
declare InsertImage(string Path, CRichEdit *re1);
}

global sub main()
{
dlg d1;
d1.Create(0,0,363,270,0x80CF0880,0,"Caption",0);
d1.AddControl(CTRICHEDIT,"",8,6,341,233,0x50B110C4,0x200,RICHEDIT_1);
d1.AddControl(CTBUTTON,"Add file...",10,244,120,22,0x50010000,0x0,BUTTON_2);
d1.AddControl(CTBUTTON,"Add image...",174,244,120,22,0x50010000,0x0,BUTTON_3);

d1.DoModal();
return true;
}


dlg::OnClose(),int
{
CloseDialog(1);
return true;
}


dlg::OnInitDialog(),int
{
return true;
}



dlg :: OnSize(int nType,int cx,int cy),int
{
CWindow *ctl = GetControl(RICHEDIT_1);
ctl->SetSize(6,6,cx-12,cy-40);
ctl = GetControl(BUTTON_2);
ctl->SetSize(10,cy-26,120,22);
ctl = GetControl(BUTTON_3);
ctl->SetSize(cx-130,cy-26,120,22);
return 0;
}



dlg::OnControl(int nID, int nNotifyCode, unsigned int hControl),int
{
select nID
{
case BUTTON_2:

if(nNotifyCode = 0)
{
InsertFile(FILEREQUEST("Select image",this, true,
"All supported types (bmp,jpg,gif,wmf,ico)|*.bmp;*.jpg;*.gif;*.wmf;*.ico||",""),
GetControl(RICHEDIT_1));
}
case BUTTON_3:

if(nNotifyCode = 0)
{
InsertImage(FILEREQUEST("Select image",this, true,
"All supported types (bmp,jpg,gif,wmf,ico)|*.bmp;*.jpg;*.gif;*.wmf;*.ico||",""),
GetControl(RICHEDIT_1));
}
}
return true;
}




CONST EM_PASTESPECIAL = 0x400 + 64;

struct DROPFILES {
    int   pFiles;
    POINT pt;
    int   fNC;
    int   fWide;
// any custom data here
dstring path[260]; // any size path|null {,path|null, ...} null
}
import int SendMessage alias SendMessageA(int q,int w,int e,void *r);
#define WM_DROPFILES 0x233

dlg :: InsertFile(string Path, CRichEdit *re1)
{
// Path or re1 = null?
DROPFILES *df = new(DROPFILES,1); // memory is GPTR
df->pFiles = &df->path - df; // offset to path member
df->fWide = false;
df->path = Path;

SendMessage(re1->m_hwnd, WM_DROPFILES,df,0);
delete df;
return;
}













#typedef HBITMAP int
#typedef HRESULT int
#typedef OLESTR pointer
#typedef STDAPI int
#typedef LONG int
#typedef BOOL int
#typedef HWND int
#typedef UINT int
#typedef HANDLE int
#typedef OLE_COLOR int
#typedef DWORD int
#typedef HGDIOBJ int
#define S_OK 0
#define CF_BITMAP 2
// temporary guids
struct GUID {int x[4];}
struct REFIID {int x[4];}

interface IUnknown
{
declare virtual QueryInterface(REFIID *riid, void *lplpObj),HRESULT;
declare virtual AddRef(),LONG;
declare virtual Release(),LONG;
}
interface IPicture : IUnknown
{
declare virtual get_Handle(/*out*/OLE_HANDLE *pHandle),HRESULT;
declare virtual get_hPal(/*out*/OLE_HANDLE *phPal),HRESULT;
declare virtual get_Type(/*out*/SHORT *pType),HRESULT;
declare virtual get_Width(/*out*/OLE_XSIZE_HIMETRIC *pWidth),HRESULT;
declare virtual get_Height(/*out*/OLE_YSIZE_HIMETRIC *pHeight),HRESULT;
declare virtual Render(
            /* [in] */ HDC hDC,LONG x,LONG y,LONG cx,LONG cy,
            /* [in] */ OLE_XPOS_HIMETRIC xSrc,
            /* [in] */ OLE_YPOS_HIMETRIC ySrc,
            /* [in] */ OLE_XSIZE_HIMETRIC cxSrc,
            /* [in] */ OLE_YSIZE_HIMETRIC cySrc,
            /* [in] */ RECT *pRcWBounds),HRESULT;

declare virtual set_hPal(OLE_HANDLE hPal),HRESULT;
declare virtual get_CurDC(/*out*/ HDC *phDC),HRESULT;
declare virtual SelectPicture(HDC hDCIn,/*out*/HDC *phDCOut,/*out*/OLE_HANDLE *phBmpOut),HRESULT;
declare virtual get_KeepOriginalFormat(/* [out] */ BOOL *pKeep),HRESULT;
declare virtual put_KeepOriginalFormat(BOOL keep),HRESULT;
declare virtual PictureChanged(),HRESULT;
declare virtual SaveAsFile(IStream pStream,BOOL fSaveMemCopy,/* [out] */ LONG *pCbSize),HRESULT;
declare virtual get_Attributes(/*out*/DWORD *pDwAttr),HRESULT;
}

declare import, OleLoadPicturePath(
OLESTR  *szURLorPath,
IUnknown *punkCaller,
DWORD    dwReserved,
OLE_COLOR clrReserved,
REFIID   *riid,
void     *ppvRet
),STDAPI;

declare import, DeleteObject(HGDIOBJ hObject),BOOL;
extern int swprintf(...);
declare import, CoInitialize(opt void *pvReserved),HRESULT;
declare import, CoUninitialize();

declare import,OpenClipboard(opt HWND hWndNewOwner),BOOL;
declare import,CloseClipboard(),BOOL;
declare import,EmptyClipboard(),BOOL;
declare import,SetClipboardData(UINT uFormat,opt HANDLE hMem),HANDLE;

extern _IID_IPicture as GUID;





dlg :: InsertImage(string Path, CRichEdit *re1)
{
HBITMAP  hBitmap = 0;
IPicture *pic;
CoInitialize(0);

OLESTR olepath = AllocHeap(len(Path)*2 +1);
swprintf(olepath, "%\x00S\x00\x00", Path); // make unicode

if S_OK=OleLoadPicturePath(olepath, 0, 0, 0, _IID_IPicture, &pic) {
pic->get_Handle(&hBitmap);

OpenClipboard(m_hwnd);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();

SendMessage(re1->m_hwnd, EM_PASTESPECIAL, CF_BITMAP, null);
DeleteObject(hBitmap);
pic->Release();
}
else {
messagebox(this,"OleLoadPicturePath failed","");
}

FreeHeap(olepath);
CoUninitialize();
}

LarryMc

Sapero,
You come through again! :o

Many Thanks!!
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

swprintf should be declared as cdecl.

import int cdecl swprintf(...);
Ionic Wind Support Team

Parker

Doesn't the compiler automatically choose cdecl when variable parameters are used?

Ionic Wind Support Team

Ionic Wind Support Team