Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как подключить COM объект в Visual C++ MFC

538
02 августа 2007 года
AVDEY
188 / / 17.11.2005
Есть COM объект comobj.dll ProgID comobj.mycom.1. Насколько я знаю надо создать объект.
CObject MyObj=CreateObject("comobj.mycom.1");
Но компилятор ругается что функция CreateObject не имеет 1 параметр.
Что не правильно делаю, или может надо подключать дополнительно какой то файл?
395
03 августа 2007 года
RelB
367 / / 09.11.2002
Цитата: AVDEY
Есть COM объект comobj.dll ProgID comobj.mycom.1. Насколько я знаю надо создать объект.
CObject MyObj=CreateObject("comobj.mycom.1");
Но компилятор ругается что функция CreateObject не имеет 1 параметр.
Что не правильно делаю, или может надо подключать дополнительно какой то файл?

Вообще-то COM объекты создаются через CoCreateInstance и клиент получает указатель на интерфейс, а не сам объект.

Советую почитать нормально про COM. Потому как знания, как мне кажется, не просто поверхностные, они вообще отсутствуют :)

538
03 августа 2007 года
AVDEY
188 / / 17.11.2005
Да ты прав я только как неделю начал учится в сторону COM-объектов. С написанием немного разобрался, и подключить с помощью LoadLibrary получается и функции вызвать. Но просто COM-объект пишется под 1С а там LoadLibrary нету :) Доступ тоько через ProgID, и не все в 1С радотает, я сам в 1С ни бум-бум. И хотелось бы проверить подключение через ProgID на Visual C++
395
03 августа 2007 года
RelB
367 / / 09.11.2002
Цитата: AVDEY
Да ты прав я только как неделю начал учится в сторону COM-объектов. С написанием немного разобрался, и подключить с помощью LoadLibrary получается и функции вызвать. Но просто COM-объект пишется под 1С а там LoadLibrary нету :) Доступ тоько через ProgID, и не все в 1С радотает, я сам в 1С ни бум-бум. И хотелось бы проверить подключение через ProgID на Visual C++

COM объекты не нужно создавать через LoadLibrary... COM объект создается только через CLSID или через ProgID... В реестре прописано, где лежит dll-ка в которой лежит COM объект с таким CLSID-ом.

538
03 августа 2007 года
AVDEY
188 / / 17.11.2005
Я где то нашел как это сделать, но после этого кода предлагают подключить *.h файл библиотеки. Я то могу, так как писал его я, и компилятор позволяет.
Но если его нету или нельзя подключить, так как в 1С.
 
Код:
IClassFactory* pCF;
    IUnknown* pUnk;
    CLSID clsid;
HRESULT hr=::CLSIDFromProgID(L"PROKSREADER.CARD.1",&clsid);
hr = CoGetClassObject( clsid, CLSCTX_INPROC, NULL,IID_IClassFactory, (void**) &pCF );
hr = pCF->CreateInstance( NULL, IID_IUnknown, (void**) &pUnk );
pCF->Release();
395
03 августа 2007 года
RelB
367 / / 09.11.2002
Цитата: AVDEY
Я где то нашел как это сделать, но после этого кода предлагают подключить *.h файл библиотеки. Я то могу, так как писал его я, и компилятор позволяет.
Но если его нету или нельзя подключить, так как в 1С.

В 1С наверное он создается через как ты говорил CreateObject в которую передается ProgID. При этом ты этот ProgID просто должен знать... Я ни разу не программировал в 1C поэтому не знаю точно...

538
03 августа 2007 года
AVDEY
188 / / 17.11.2005
Ну и я пока не программировал, но чувствую прийдеться.
ProgID я программисту сообщил. И получается. Написал, отослал, получил от него результат, и переделуеш то что у него не работает.
Я думал что может так же можно и в С++ так как клас CObject и функция CreateObject существуют, что бы приблизить проверку к похожей на 1С.
395
03 августа 2007 года
RelB
367 / / 09.11.2002
Цитата: AVDEY
Ну и я пока не программировал, но чувствую прийдеться.
ProgID я программисту сообщил. И получается. Написал, отослал, получил от него результат, и переделуеш то что у него не работает.
Я думал что может так же можно и в С++ так как клас CObject и функция CreateObject существуют, что бы приблизить проверку к похожей на 1С.

Попробуй не в C++, а скажем в VB, VBA и т.д.

538
03 августа 2007 года
AVDEY
188 / / 17.11.2005
Так я не работал в этых средах разработки.
И компиляторов сейчас нету.
370
03 августа 2007 года
koval
443 / / 29.08.2005
Цитата: AVDEY
Я где то нашел как это сделать, но после этого кода предлагают подключить *.h файл библиотеки. Я то могу, так как писал его я, и компилятор позволяет.
Но если его нету или нельзя подключить, так как в 1С.
 
Код:
IClassFactory* pCF;
    IUnknown* pUnk;
    CLSID clsid;
HRESULT hr=::CLSIDFromProgID(L"PROKSREADER.CARD.1",&clsid);
hr = CoGetClassObject( clsid, CLSCTX_INPROC, NULL,IID_IClassFactory, (void**) &pCF );
hr = pCF->CreateInstance( NULL, IID_IUnknown, (void**) &pUnk );
pCF->Release();


Первое что ты должен сделать для клиета это инитиализировать СОМ библиотеку
с помощью

 
Код:
CoInitialize(NULL);
...........................................................

CoUninitialize();

Если уж сильно хочется использовать указатель на фабрику классов то
Код:
CoInitialize(NULL);
HRESULT hr;
IClassFartory *pFac = NULL;
//точно также создаешь и указатель на нужный интерфейс
hr = CoGetClassObject(/*CLSID - твоего класса*/,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(void**)&pFac);
hr = pFac->CreateInstance(NULL,/*IID интерфейса и (void**)указатель на интерфейс*/);
//потом только через QueryInterface
...............................................................................
//освобождаешь ресурсы
if(pFac)
     pFac->Release();
...................................
CoUninitialize();


а h- файл должен быть по любому.
там должны храниться IID и CLSID
538
04 августа 2007 года
AVDEY
188 / / 17.11.2005
Проще, как оказалось, это все самому и протестировать в 1С, ничего там сложного нет, ну по крайней мере в создании нескольких кнопок и их обработчиков.
42K
25 апреля 2010 года
blackswan
8 / / 09.11.2008
Мне необходимо вызвать функцию CheckSpelling (для проверки орфографии) с помощью СОМ. Она является методом класса Application, который в свою очередь является членом класса Word. В хелпе Word нашел вот такое её описание:
Function CheckSpelling(Word As String, [CustomDictionary], [IgnoreUppercase], [MainDictionary], [CustomDictionary2], [CustomDictionary3], [CustomDictionary4], [CustomDictionary5], [CustomDictionary6], [CustomDictionary7], [CustomDictionary8], [CustomDictionary9], [CustomDictionary10]) As Boolean
т.е. как бы только первый параметр - проверяемое слово - является обязательным. Сначала хочу взять ID имени метода и параметра через GetIDsOfNames, потом вызываю через Invoke

Код:
CoInitialize(NULL);
    CLSID clsid;
    HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);

    IDispatch *pWApp;
    DISPID dispid[2];
    if(SUCCEEDED(hr))
    {
        hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pWApp);
        if(SUCCEEDED(hr))
        {
            LCID lcid = GetSystemDefaultLCID();
            lcid = 1033;
            LPOLESTR rgszNames[2];
            rgszNames[0] = L"CheckSpelling";
            rgszNames[1] = L"Word";
            pWApp->GetIDsOfNames(IID_NULL,rgszNames,2,lcid,dispid);
            WORD wFlags = DISPATCH_METHOD;
            CComVariant varResult;
            EXCEPINFO excepInfo;
            ZeroMemory(&excepInfo, sizeof(excepInfo));
            UINT uArgErr;
            DISPPARAMS dp = {NULL,NULL,0,0};
            dp.cArgs = 1;
            dp.cNamedArgs = 1;
            dp.rgdispidNamedArgs = &dispid[1];

            dp.rgvarg = new VARIANT[dp.cArgs];
            dp.rgvarg[0].vt = VT_BSTR;
            dp.rgvarg[0].bstrVal = SysAllocString(OLESTR("Hello"));
            //LOCALE_SYSTEM_DEFAULT
            hr = pWApp->Invoke(dispid[0],IID_NULL, lcid, wFlags, &dp, &varResult, &excepInfo, &uArgErr);
                    SysFreeString(dp.rgvarg[0].bstrVal);
            pWApp->Release();
            delete [] dp.rgvarg;
               }



Экземпляр Ворда создается, GetIdsOfNames работает без ошибок, возвращает первый ID (сам метод) равным 0х144, второй (параметр Word) почему-то нуль. Может так и должно быть? Потом передаю всего один параметр - строку "Hello" для примера, вызываю Invoke, он не выдает ошибок, эксепшинов, результат S_OK, в параметре varResult должен быть результат функции CheckSpelling - boolean (типа орфографически правильно или нет). Но какое бы я слово ни задавал (орфографически верное или нет), он всегда возвращает один параметр {False VT_BOOL}. От кода локали это не зависит, ставил LOCALE_SYSTEM_DEFAULT, 1033 (United States), всё одинаково
2.2K
26 апреля 2010 года
REFOT
181 / / 08.04.2005
Ну, наверное, осталось только указать словарь, по которому будет проводиться проверка, через параметр MainDictionary.
Во всяком случае, данный код на слово "Привет" вернул true, а на слово "Прапвет" вернул false. Т.е у меня по умолчанию для проверки используется русский словарь.
42K
26 апреля 2010 года
blackswan
8 / / 09.11.2008
да, верно, однако я не знаю, как задать MainDictionary, по идее его можно получить в VBasic вот так
Set dict = Application.Languages(wdEnglishUS).ActiveSpellingDictionary
где wdEnglishUS = 1033, но как это представить в С++ в СОМ? Как обратиться к элементу коллекции и получить его свойство через тот же Invoke?
2.2K
27 апреля 2010 года
REFOT
181 / / 08.04.2005
Я попробовал сделать вот так:
Код:
HRESULT getDictionary(LPDISPATCH app, long id, LPDISPATCH* ppd)
{
    if(app == NULL || ppd == NULL) return E_INVALIDARG;

    HRESULT hr = S_OK;
    DISPID dispid = 0;
    CComBSTR bstr = _T("Languages");
    if(SUCCEEDED(hr=app->GetIDsOfNames(IID_NULL,&bstr,1,0,&dispid)))
    {
        EXCEPINFO excepInfo = {0};
        VARIANT varResult;
        VariantInit(&varResult);

        DISPPARAMS dispparams;
        memset(&dispparams,0,sizeof(dispparams));

        UINT uArgErr =  -1;
        hr = app->Invoke(dispid,IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varResult, &excepInfo, &uArgErr);
        if(SUCCEEDED(hr))
        {  
            LPDISPATCH pLanguages = NULL;
            hr = varResult.pdispVal->QueryInterface(IID_IDispatch, (void**)&pLanguages);
            VariantClear(&varResult);

            if(SUCCEEDED(hr))
            {
                DISPID dispid = 0;
                CComBSTR bstr = _T("Item");
                if(SUCCEEDED(hr=pLanguages->GetIDsOfNames(IID_NULL,&bstr,1,0,&dispid)))
                {
                    dispparams.cArgs = 1;
                    dispparams.rgvarg = new VARIANT[dispparams.cArgs];
                    dispparams.rgvarg[0].vt = VT_I4;
                    dispparams.rgvarg[0].lVal = id;
       
                    hr = pLanguages->Invoke(dispid,IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varResult, &excepInfo, &uArgErr);
                    delete [] dispparams.rgvarg;
               
                    if(SUCCEEDED(hr))
                    {
                        LPDISPATCH pDictionary = NULL;
                        hr = varResult.pdispVal->QueryInterface(IID_IDispatch, (void**)&pDictionary);
                        VariantClear(&varResult);
               
                        if(SUCCEEDED(hr))
                        {
                            DISPID dispid = 0;
                            CComBSTR bstr = _T("ActiveSpellingDictionary");
                            if(SUCCEEDED(hr=pDictionary->GetIDsOfNames(IID_NULL,&bstr,1,0,&dispid)))
                            {
                                memset(&dispparams,0,sizeof(dispparams));
                                uArgErr =  -1;
                                hr = pDictionary->Invoke(dispid,IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varResult, &excepInfo, &uArgErr);
                                if(SUCCEEDED(hr)){
                                    hr = varResult.pdispVal->QueryInterface(IID_IDispatch, (void**)ppd);
                                    VariantClear(&varResult);
                                }
                            }
                            pDictionary->Release();
                        }
                    }
                }
                pLanguages->Release();
            }
        }
    }
    return hr;
}

.......

::CoInitialize(NULL);

    CLSID clsid;
    HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);

    IDispatch *pWApp;
    if(SUCCEEDED(hr))
    {
        hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pWApp);
   
        if(SUCCEEDED(hr))
        {
            LPDISPATCH pd = NULL;
            if(SUCCEEDED(hr=getDictionary(pWApp, 1033 /*wdEnglishUS*/, &pd)))
            {
                DISPID dispid = 0;            
                CComBSTR bstr = _T("CheckSpelling");
                pWApp->GetIDsOfNames(IID_NULL,&bstr,1,0,&dispid);
               
                DISPPARAMS dp = {0};   
                dp.cNamedArgs = 4;
                dp.cArgs = 4;
                        dp.rgdispidNamedArgs = new DISPID[dp.cNamedArgs];
                dp.rgvarg = new VARIANT[dp.cArgs];
   
                dp.rgdispidNamedArgs[0] = 0;
                CComBSTR text = _T("hello");
                dp.rgvarg[0].vt = VT_BSTR;
                dp.rgvarg[0].bstrVal = text;

                VARIANT CustomDictionary;
                CustomDictionary.vt = VT_EMPTY;
                CustomDictionary.bstrVal = NULL;

                dp.rgdispidNamedArgs[1] = 1;
                dp.rgvarg[1].vt = VT_VARIANT|VT_BYREF;
                dp.rgvarg[1].pvarVal = &CustomDictionary;

                VARIANT varIgnoreUppercase;
                varIgnoreUppercase.vt = VT_BOOL;
                varIgnoreUppercase.boolVal = VARIANT_TRUE;

                dp.rgdispidNamedArgs[2] = 2;
                dp.rgvarg[2].vt = VT_VARIANT|VT_BYREF;
                dp.rgvarg[2].pvarVal = &varIgnoreUppercase;

                VARIANT varMainDictionary;
                varMainDictionary.pdispVal = pd;
                varMainDictionary.vt = VT_DISPATCH;

                dp.rgdispidNamedArgs[3] = 3;
                dp.rgvarg[3].vt = VT_VARIANT|VT_BYREF;
                dp.rgvarg[3].pvarVal = &varMainDictionary;

                UINT uArgErr = -1;
                CComVariant varResult;
                EXCEPINFO excepInfo = {0};
                hr = pWApp->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dp, &varResult, &excepInfo, &uArgErr);  
                   delete [] dp.rgvarg;
            }
                        pWApp->Release();
        }
    }


Но проверка английского всё равно не работает.
Не знаю, из-за чего, но уже нет ни времени, ни желания разбираться дальше...
42K
28 апреля 2010 года
blackswan
8 / / 09.11.2008
спасибо за помощь
применил этот вариант, и сначала результат возвращал "true" на "Hello" и других словах, но потом снова "false" , потом снова "true", и от чего это может зависеть так и не понял, на русские слова всегда теперь возвращает true. Однако главное, что приложение отказывается выгружать WINWORD.exe после Release(), также заметил, что CInitialize возвращает S_FALSE, как будто СОМ уже инициализирован(это возможно, часть кода писал не я), поэтому как бы нельзя вызывать CoUninitialize.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог