Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перехват событий VB ActiveX 
:(
    Опции темы
SnowMan
Дата 18.9.2006, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 18.9.2006

Репутация: нет
Всего: нет



В аттаче простенький VB ActiveX с одним событием, подскажите как перехватить события этого ActiveX объекта?

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  EventDLL.zip 2,11 Kb
PM MAIL   Вверх
Pulse69
Дата 22.9.2006, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 1
Всего: 10



Как именно перехватить? MFC, ATL?
Если нужно, могу дать код подключения к событиям VB через сток.


--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
SnowMan
Дата 25.9.2006, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 18.9.2006

Репутация: нет
Всего: нет



Подкинь пожайлуста.
PM MAIL   Вверх
Pulse69
Дата 26.9.2006, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 1
Всего: 10



В MFC попроще, там просто импортируется ActiveX контрол, у которого есть все события, 
а для ATL я нашёл только такой способ:

Во-первых нужен класс стока событий, ктороый должен реализовывать интерфейс IDispatch.

EventSink.h
Код

#pragma once

//    Вызывается при вызове метода QueryInterface
HRESULT __stdcall CallThisForEveryQI(void* pv, REFIID riid, void** ppv, DWORD dw);

//*-------------------------------------------------------------
//    Служит для перехвата событий, приходящих от COM-сервера
//*-------------------------------------------------------------        
class CEventSink: 
    public CComObjectRootEx<CComSingleThreadModel>,
    public IDispatch
{
public:
    BEGIN_COM_MAP(CEventSink)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY_FUNC_BLIND(0, CallThisForEveryQI)
    END_COM_MAP()

    STDMETHOD(GetTypeInfoCount)(UINT* pctinfo);
    STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo);
    STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, 
                             UINT cNames, LCID lcid, DISPID* rgdispid);
    
    STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, 
                      WORD wFlags, DISPPARAMS* pdispparams, 
                      VARIANT* pvarResult, EXCEPINFO* pexcepinfo, 
                      UINT* puArgErr);

    CEventSink(void);
    ~CEventSink(void);
};




EventSink.cpp
Код

#include "StdAfx.h"
#include "EventSink.h"


CEventSink::CEventSink(void){}
CEventSink::~CEventSink(void){}

//
//    Возвращает указатель на интерфейс
//
HRESULT __stdcall CallThisForEveryQI(void* pv, REFIID riid, void** ppv,
                                     DWORD dw)
{
    //    Возвращает вызывающему объекту указатель на интерфейс стока:
    *ppv = pv;
    return S_OK; 
}

//*--------------------------------------
//    Вызывается при получании события. 
//    ID Событий содержится в переменной dispidMember.
//    аргументы находятся в DISPPARAMS.
//    Если известны имена событий, то их идентификаторы можно получить через функцию COM-сервера GetIDsOfNames
//*--------------------------------------
STDMETHODIMP CEventSink::Invoke(DISPID dispidMember, REFIID riid, 
                             LCID lcid, WORD wFlags, 
                             DISPPARAMS* pdispparams, 
                             VARIANT* pvarResult, EXCEPINFO* pexcepinfo, 
                             UINT* puArgErr)
{    

    TCHAR *flag;
    switch (wFlags)
    {
    case DISPATCH_METHOD:
        flag=L"wflags= DISPATCH_METHOD";
        break;
    case DISPATCH_PROPERTYGET:
        flag=L"wflags= DISPATCH_PROPERTYGET";
        break;
    case DISPATCH_PROPERTYPUT:
        flag =L"wflags= DISPATCH_PROPERTYPUT";
        break;
    case DISPATCH_PROPERTYPUTREF:
        flag = L"wflags= DISPATCH_PROPERTYPUTREF";
        break;
    }

    
    TCHAR txt[512];
    _stprintf_s( txt, 512, TEXT("Event fired. EVENT ID: %d\n%s\nNum of params: %d\n"), dispidMember, flag, pdispparams->cArgs );
    OutputDebugString( txt );
    return S_OK;
}


STDMETHODIMP CEventSink::GetTypeInfoCount(UINT* pctinfo)
{
    return  E_NOTIMPL;
}

STDMETHODIMP CEventSink::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
    return  E_NOTIMPL;
}

STDMETHODIMP CEventSink::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, 
                                    DISPID* rgdispid)
{
    return  E_NOTIMPL;
}



И функции для подписки на событий сервера
Код


LPCONNECTIONPOINT lpCPT;
IDispatch *pDisp;                    // Pointer to the server object
IDispatch *pIDispatchobjevent;        // Pointer to the event object
DWORD dwCookie;                        // For Advise / Unadvise
LPCONNECTIONPOINT lpCPT;            // Pointer to the Connection Point
IUnknown *pUnkDispatchSink;            // Sink interface IUnknown pointer
CComObject<CPollEventSink> *pMySink;// Sink interface pointer

//    Подписывается на события сервера
void CMyClass::StartMonitoring(IDispatch *obj)
{
    hr = S_OK;

    pIDispatchobjevent = (IDispatch*)NULL;// Pointer to the event object
    lpCPT = NULL;       // Pointer to the Connection Point

    //    Попытаемся подписаться на события

    try
    {
        LPENUMCONNECTIONPOINTS lpEnumCPTS;
        unsigned long count;

        // Выделяем память под сток событий
        CComObject<CPollEventSink>::CreateInstance(&pMySink);
        
        // Получаем IUnknown-интерфейс стока событий
        TEST_COM_CALL( pMySink->QueryInterface(IID_IUnknown, (void**)&pUnkDispatchSink) );


        //    Получаем доступ к интерфейсу, позволяещему пречислить все точки соединения
        IConnectionPointContainer* pCPContainer;

        // Получаем доступ к точкам соединения сервера 
        obj->QueryInterface(IID_IConnectionPointContainer, 
                                   (void**)&pCPContainer);
        
        pCPContainer->EnumConnectionPoints(&lpEnumCPTS);
        lpEnumCPTS->Reset();
        
        //    Получаем точки соединения
        while(S_OK==(hr = lpEnumCPTS->Next(1, &lpCPT, &count)))
        {
            // Связываем сервер и сток
            hr = lpCPT->Advise(pUnkDispatchSink, &dwCookie);
        }
        
        //    Чистим память
        TEST_COM_CALL( lpEnumCPTS->Release() );
        lpEnumCPTS = NULL;
    }
    catch( ... )
    {
        
    }
}
//    Отписывается от событий сервера
void CMyClass::StopMonitoring()
{
    //    Отписываемся от стока событий
    lpCPT->Unadvise(dwCookie);
    lpCPT->Release(); 
}




В двух словах:
Создаём реализацию IDispatch, находим точки соединения в COM-сервере, делаем Advise для связи экземпляра
стока событий с сервером и радуемся. 

Кстати, для того, чтобы события от VB компонентов приходили нормально, нужно в потоке стока событий
поместить цикл обработки сообщений.

Вроде, всё. Если будут вопросы, пиши.
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: COM/DCOM/ActiveX/ATL/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0422 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.