Re: EM_SETOLECALLBACK

From: anony*mouse (anonytmouse_at_subdimension.com)
Date: 04/05/04


Date: 5 Apr 2004 03:19:38 -0700


"Mike H" <mikehg1@removethis foraccess-4-free.com> wrote in message news:<5686b119ee3f1905314684af40f88ef0@news.teranews.com>...
> Does anyone have a working example of how to setup the olecallback for a
> richedit control. I'm pretty much an idiot when it comes to this com/ole
> stuff, so any info would be greatly appreciated. Plain C would be the
> preferred language.

Here is a working implementation of IRichEditOleCallback in plain C
(tested with MSVC7 and LCC-WIN32).

[code]
#include <objbase.h>
#include <richedit.h>
#include <richole.h>
#include <stdlib.h>
#include <stddef.h>

    // --- Utility macros ---
#define OleQueryInterface(this, riid, ppv) \
     (this)->lpVtbl->QueryInterface(this, riid, ppv)

#define OleAddRef(this) \
     (this)->lpVtbl->AddRef(this)

#define OleRelease(this) \
     (this)->lpVtbl->Release(this)

#define IMPL(class, member) \
    (&((class *)0)->member == This, \
     ((class *) (((INT_PTR) This) - offsetof (class, member))))

#undef INTERFACE
#define INTERFACE IRichEditOleCallback

typedef struct tagCReCallback {
    INTERFACE IRichEditOleCallbackIFace;

    ULONG cRef;

    /* Declare any class data you need here */

} CReCallback;

   // --- IUnknown methods ---
static STDMETHODIMP IREOC_QueryInterface(THIS_ REFIID riid, void **
ppv)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    if (IsEqualIID (riid, &IID_IUnknown) ||
        IsEqualIID (riid, &IID_IRichEditOleCallback))
    {
        *ppv = &ThisObj->IRichEditOleCallbackIFace;
    }
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    OleAddRef ((INTERFACE *) *ppv);

    return NOERROR;
}

static STDMETHODIMP_(ULONG) IREOC_AddRef(THIS)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return InterlockedIncrement(&ThisObj->cRef);
}

static STDMETHODIMP_(ULONG) IREOC_Release(THIS)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    if (InterlockedDecrement(&ThisObj->cRef) == 0)
    {
        free(ThisObj);
        return 0;
    }
    return ThisObj->cRef;
}

   // --- IRichEditOleCallback methods ---
static STDMETHODIMP IREOC_GetNewStorage(THIS_ LPSTORAGE * lplpstg)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_GetInPlaceContext(THIS_
                                       LPOLEINPLACEFRAME * lplpFrame,
                                       LPOLEINPLACEUIWINDOW * lplpDoc,
                                       LPOLEINPLACEFRAMEINFO
lpFrameInfo)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_ShowContainerUI(THIS_ BOOL fShow)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_QueryInsertObject(THIS_ LPCLSID lpclsid,
                                            LPSTORAGE lpstg, LONG cp)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_DeleteObject(THIS_ LPOLEOBJECT lpoleobj)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_QueryAcceptData(THIS_ LPDATAOBJECT
lpdataobj,
                                     CLIPFORMAT * lpcfFormat, DWORD
reco,
                                     BOOL fReally, HGLOBAL hMetaPict)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_ContextSensitiveHelp(THIS_ BOOL fEnterMode)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_GetClipboardData(THIS_ CHARRANGE * lpchrg,
                                           DWORD reco,
                                           LPDATAOBJECT * lplpdataobj)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    MessageBox(NULL, TEXT("### GetClipboardData"), NULL, 0);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_GetDragDropEffect(THIS_ BOOL fDrag,
                                            DWORD grfKeyState,
                                            LPDWORD pdwEffect)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static STDMETHODIMP IREOC_GetContextMenu(THIS_ WORD seltype,
                                         LPOLEOBJECT lpoleobj,
                                         CHARRANGE * lpchrg,
                                         HMENU * lphmenu)
{
    CReCallback * ThisObj = IMPL(CReCallback,
IRichEditOleCallbackIFace);

    return E_NOTIMPL;
}

static const IRichEditOleCallbackVtbl vtblIRichEditOleCallback = {

    IREOC_QueryInterface, IREOC_AddRef, IREOC_Release,

    IREOC_GetNewStorage, IREOC_GetInPlaceContext,
    IREOC_ShowContainerUI, IREOC_QueryInsertObject,
    IREOC_DeleteObject, IREOC_QueryAcceptData,
    IREOC_ContextSensitiveHelp, IREOC_GetClipboardData,
    IREOC_GetDragDropEffect, IREOC_GetContextMenu
};

CReCallback * new_CReCallback(void)
{
    CReCallback * ThisObj = calloc(1, sizeof(CReCallback));

    if (ThisObj)
    {
        ThisObj->cRef = 1;
        ThisObj->IRichEditOleCallbackIFace.lpVtbl =
            (IRichEditOleCallbackVtbl *) &vtblIRichEditOleCallback;
    }

    return ThisObj;
}

void delete_CReCallback(CReCallback * pCallback)
{
    OleRelease(&pCallback->IRichEditOleCallbackIFace);
}
[/code]

The header for all that is:

[header]
    typedef struct tagCReCallback CReCallback;
    CReCallback * new_CReCallback(void);
    void delete_CReCallback(CReCallback * pCallback);
[/header]

and to hook it up to your rich edit control:

[code]
    CReCallback * pCallback = new_CReCallback();

    SendMessage(hwndRichEdit, EM_SETOLECALLBACK, 0, (LPARAM)
pCallback);

    delete_CReCallback(pCallback);
[/code]

As it stands the ten callback functions simply do nothing and return
E_NOTIMPL. It is your responsibility to add code and return an
appropriate value.

You can add calls to MessageBox() or OutputDebugString() to trace
incoming calls as demonstrated in IREOC_GetClipboardData() above.

If you would like further information on implementing COM interfaces
in plain C you should start with the COM programmer's cookbook(at
least the first half):
http://msdn.microsoft.com/library/techart/msdn_com_co.htm

Another good article is "Display a Web Page in a Plain C Win32
Application":
http://www.codeguru.com/Cpp/I-N/ieprogram/article.php/c4379/

You can find implementations in plain C for many COM interfaces by
searching for the interface name along with "lpVtbl". Searching for
"IRichEditOleCallback lpVtbl" produces this result:
http://cvs.sourceforge.net/viewcvs.py/miranda-icq/Plugins/srmm/msgs.c?rev=1.15

NOTE: My email address is invalid.



Relevant Pages

  • Re: Good COM Interface Design
    ... interface's IID after it's publish is plain wrong. ... clients know exactly how to bind/call it. ... There is a lot of trickery associated with interface extensions in COM, ...
    (microsoft.public.vc.atl)
  • Re: Reproducible FireFox crash.
    ... >> I was struck by a stupidity in Thunderbird on Friday. ... >> lets you specify which domains to send HTML mail to, ... > but it is a stupid bit of interface for sure. ... I only ever send plain text messages myself; I think I was just noodling ...
    (uk.comp.sys.mac)
  • Re: Read HTML messages
    ... interface" for their users. ... you can normally access these ... interfaces to read any "html only" message. ... Notify your correspondents to email you in "plain text only" or "both ...
    (microsoft.public.pocketpc)
  • Gateway Authentificaton Method
    ... password (plain text) for outgoing tcp/udp connection from internal ... interface to external' one using linux, ...
    (Security-Basics)