Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Диалог с ActiveX в dll с использ-ем общей DLL MFC, всё работает пока не вставлю ActiveX 
:(
    Опции темы
Finarfin
Дата 22.7.2010, 01:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я пишу dll плагина-отладчика для Mathcad. Вот так это всё делается (на всякий случай). 

Есть успешно работающая dll, по команде из Mathcad`а создающая интерфейсный поток с модальным диалогом отладчика, и по другой команде его завершающая. DLL - "обычная с использованием общей DLL MFC". Резво так окошко вылезает и прячется smile

Дальше мне надо добавить в диалог компонент ActiveX (NTGraph). Exe-шники с этим компонентом работают. Соответствующий OCX регистрирую (успешность регистрации подтверждается отсутствием характерной ошибки Debug Assertion Failed! Program: C:\блаблабла.exe File: блаблабла\occcont.cpp Line: 926). Но окошко появляться не жалает. Никаких runtime error, просто не появляется. 

Пробовал другие ActiveX на диалог наляпывать - всё одно: без компонентов - робит, с компонентами - не робит.

КОД

Код
mcd_debug.cpp
#define AMS AFX_MANAGE_STATE(AfxGetStaticModuleState())
/*.........*/
LRESULT ShowDeb(COMPLEXSCALAR * const Result,const COMPLEXSCALAR * const x)
{AMS;        // та самая волшебная функция, вызывающая и убивающая поток с диалогом
            Result->real = 0;
    if ((x->real == 1) & (!vidim))// показ окна дебаггера
    {
            if (!myVal.IsEmpty()) myVal.RemoveAll(); // Чистим глобальный массив
            CRuntimeClass * RtC = RUNTIME_CLASS(CMyUIThread);
            pThread = AfxBeginThread(RtC);// запустили поток с окном
            
            if (pThread->m_hThread == NULL)   Result->real = 0;    // FAIL   // кстати другая уже тема, но еще не понял как правильно проверить успешность
            else {vidim = TRUE; Result->real = 1;}                // SUCCESS
    }
    else if (vidim) // уничтожить окно дебаггера
    {
        PostThreadMessage( pThread->m_nThreadID, WM_QUIT, 0, 0);// завершаем поток

            if (pThread->m_hThread == NULL)   Result->real = 0;    // FAIL
            else {vidim = FALSE; Result->real = 1;}                // SUCCESS
    }
Result->imag = 0;return 0;
}

/*.........*/

BOOL Cmcd_debugApp::InitInstance()
{
        AfxEnableControlContainer();        // использовать ActiveX ()
        CWinApp::InitInstance();
/*.........*/
return(TRUE);
}



В классе потока CMyUIThread, 
Код
MyUIThread.cpp

BOOL CMyUIThread::InitInstance()
{
    AfxEnableControlContainer();            // если убрать здесь и в Cmcd_debugApp::InitInstance()  или в одном из них - тоже не запускается
    myDlg.DoModal();                    // Запускаем единственное окно дебаггера myDlg - public член класса CMyUIThread
    return TRUE;
}

int CMyUIThread::ExitInstance()
{
myDlg.~CAdvDlg();        // вот кстати тоже хз, как правильнее окно уничтожить
    return CWinThread::ExitInstance();
}// всё остальное по умолчанию


И в классе вызываемого потоком модального окна
Код
AdvDlg.cpp

// Конструктор, деструктор - по умолчанию

void CAdvDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT1, myEdit);
    DDX_Text(pDX, IDC_EDIT1, lastVal);
    //DDX_Control(pDX, IDC_NTGRAPHCTRL1, m_Graph1);   // пробую закоментировать/раскомментировать - влияния нет
}

BOOL CAdvDlg::OnInitDialog()
{
        CDialog::OnInitDialog();
        //m_Graph1.SetFrameStyle(0);                    // прямоугольник без картинки
        //m_Graph1.SetPlotAreaColor(RGB(255,255,255));        // белый фон
        //m_Graph1.SetControlFrameColor(RGB(255,255,255));        // инициализация компонента - пробую закоментить-раскоментить - не влияет
return TRUE;        // пробовал FALSE. по смыслу у меня фокус не стоит ни на одном элементе, поэтому ТРУ
}


Вообще диалог создан редактором ресурсов VS
В основном всё поумолчательное

ОТЛАДКА
При создании потока проходит конструктор диалога CAdvDlg
Доходит до myDlg.DoModal(); в CMyUIThread::InitInstance()
До BOOL CAdvDlg::OnInitDialog() не доходит. Просто передает управление маткаду, так и не показав окно. Вглубь не могу отследить, ибо "Не загружена символьная информация ни для одного фрейма стека вызовов. Невозможно показать исходный код." 


Вот. Требуется брэйншторминг. Задача осложняется тем, что я могу чинить только свою сторону и не знаю что там делает Mathcad, потому что я его не писал smile Не знаю, как влияет на это вызывающее приложение, вообще как оно может повлиять, если у всё это в другом потоке? Значит косяк на моей стороне...

Может вообще не так делаю? Никогда не втыкал ActiveX в dll.

Это сообщение отредактировал(а) Finarfin - 22.7.2010, 01:31
PM MAIL WWW   Вверх
Finarfin
Дата 22.7.2010, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Так, во-первых я ступил с тем, что каждый COM компонент считается зарегестрированным один раз по тому пути, по которому он был зареген в последний раз. Поэтому если надо перерегестрировать в другом месте, то надо видимо заново помещать компонент в диалог. Только непонятно куда лучше его класть - к dll или к экзешнику...

... хотя экзешнику с этим компонентом пофигу где он зареген, работает если OCX лежит в той же директории...

Вобщем продолжаю  smile 

Это сообщение отредактировал(а) Finarfin - 22.7.2010, 23:00
PM MAIL WWW   Вверх
Finarfin
Дата 22.7.2010, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Что то я подозреваю что где-нибудь слажал в классе диалога....
Господа, взгляните незамыленным взглядом...

Код

// AdvDlg.h

#pragma once

#include "afxwin.h"
#include "stdafx.h"            
#include "ntgraph.h"            // ГРАФИКИ
#include "myArr.h"                // Резиновые массивы

class CAdvDlg : public CDialog
{    // диалоговое окно CAdvDlg
DECLARE_DYNAMIC(CAdvDlg)

public:
    DECLARE_MESSAGE_MAP()

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // поддержка DDX/DDV
    CNTGraph    m_Graph1;        // Компонент График

public:

    CAdvDlg(CWnd* pParent = NULL);   // стандартный конструктор
    virtual ~CAdvDlg();
        
    enum { IDD = IDD_DIALOG1 };// Данные диалогового окна

    void DrawGraph();            // функция рисования графика
    
    BOOL OnInitDialog();        // инициализация диалога
    void OnPaint();  

    afx_msg void OnBnClickedPause();
    afx_msg void OnBnClickedStep();
    afx_msg void OnBnClickedBreak();
    CEdit myEdit;
    afx_msg void OnBnClickedPlotprop();

};

//***********************************
// AdvDlg.cpp

// AdvDlg.cpp: файл реализации
//
#include "stdafx.h"
#include "AdvDlg.h"

// диалоговое окно CAdvDlg

// Объявим внешние глобальные переменные
extern CArray <CMyArr,CMyArr> myVal;    // все они уже определены в cmd_debug.cpp
extern double lastVal;                    
extern double minVal;
extern double maxVal;
extern CEvent UpdPlot;    // Событие обновления графика

IMPLEMENT_DYNAMIC(CAdvDlg, CDialog)

CAdvDlg::CAdvDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CAdvDlg::IDD, pParent)
{
}

CAdvDlg::~CAdvDlg()
{
}

void CAdvDlg::OnPaint()    // перерисовка. возможно здесь потребуется обновление графика
{
    CDialog::OnPaint();        // до сюда не доходит
}

void CAdvDlg::DoDataExchange(CDataExchange* pDX)
{     // сюда не доходит
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT1, myEdit);
    DDX_Text(pDX, IDC_EDIT1, lastVal);
    DDX_Control(pDX, IDC_NTGRAPHCTRL1, m_Graph1);
}

BOOL CAdvDlg::OnInitDialog() 
{   // сюда не доходит
        CDialog::OnInitDialog();
        m_Graph1.SetFrameStyle(0);                    // прямоугольник без картинки
        m_Graph1.SetPlotAreaColor(RGB(255,255,255));        // белый фон
        m_Graph1.SetControlFrameColor(RGB(255,255,255));

return 0;
}

BEGIN_MESSAGE_MAP(CAdvDlg, CDialog) // после DoModal в классе потока идёт сюда, и попадает сюда несколько раз. На два попадания на BEGIN_MESSAGE_MAP приходится одно попадание на END_MESSAGE_MAP()
    ON_WM_PAINT()
// кнопки, до которых всё равно пока не доходит
END_MESSAGE_MAP()


void CAdvDlg::DrawGraph()
{
// всё равно пока не используется
}


// обработчики сообщений 
// нафиг, до них всё равно не доходит



Если кто-то мог бы и сам проект посмотреть, то вообще чудно. Но, боюсь, требуется Mathcad 14 для погружения в ситуацию. Проект в аттаче


Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  mcd_debug_2.zip 211,79 Kb
PM MAIL WWW   Вверх
ivanychhh
Дата 31.8.2011, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Судя по дате последнего поста, все уже сделано и работает! У меня похожая проблема! Пустой диалог открывается,  стоит навесить на него ActiveX, так все ломается. 

Подскажи пожалуйста! Как решил проблему?

Код

BOOL ret = myDlg.Create(IDD_KKMDLG);
     if(!ret)   //Если окно не создано.
    {
       AfxMessageBox(_T(" Креате не фурычит!"));
    }
    
      myDlg.ShowWindow(SW_SHOW);
 

Без активХ диалог поднимается, с АктивХ Выдается соответствующий месседжбокс, и диалог не поднимается... 


Это сообщение отредактировал(а) ivanychhh - 31.8.2011, 15:41
PM MAIL   Вверх
Finarfin
Дата 31.8.2011, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Проблема решена отказом от элемента ActiveX в том плагине который я тогда писал. 
Кстати вот он
Так что мой ответ – не знаю smile
PM MAIL WWW   Вверх
Finarfin
Дата 31.8.2011, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ой. Стоп. Эта тема про вызов диалога из DLL. Если у тебя проблемы с вызовом диалога с элементом не из dll а из приложения то это совсем другая проблема. Там надо в самом приложении, откуда вызывается диалог разрешить ActiveX.

Код

BOOL CYourApplication::InitInstance()
{
    AfxEnableControlContainer();        // Разрешить ActiveX 

// ..........

}

PM MAIL WWW   Вверх
ivanychhh
Дата 1.9.2011, 08:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Да вот как раз в ДЛЛ-ку и надо обернуть этот активХ. При чем, длл-ка должна привязываться к приложению явным образом, т.е. на лету. Чтоб ее отсутствие(за ненадобностью) не влияло на работу приложения, т.к. работать с этой дллкой и этим элементом, будут всего 4 компа, заказчика. И выпускать для них какие-то спецверсии, как-то не комильфо. Ну ладно, буду ковать дальше сам. Если что получится, напишу. Спасибо! 
PM MAIL   Вверх
ivanychhh
Дата 2.9.2011, 08:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Решил задачку. У меня нет отдельного потока, в котором должен открываться этот диалог с АктивХ. Ниже приведу свой рецепт. Может кому-то поможет. Помощь в решении своей проблемы я нашел здесь.

И так. Как открыть диалог с контролом ActiveX из MFC Dll:

1. Создаем проект MFC DLL. (Можно со статическим подключением MFC кому как нравится.)
2. Сдобавляем в ресурсы диалог, и создаем для него класс.
3. Добавляем активХ контрол (в VS 2008, выбрав в контекстном меню соответствующий пункт).
4. Создаем для него переменную (все тоже контекстное меню в помощь).
5. Добавляем в главный срр-шник Dll экспортную функцию.
Код


#define EXPORTAPI(TYPE) extern "C" TYPE _declspec(dllexport)

//...

EXPORTAPI (void)  Test(void)
{    
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     CMyDlg myDlg; //объявляем наш диалог
    
     myDlg.DoModal();
    

}


6. В Функции InitInstace, нашей Dll, делаем следующее:
Код

BOOL CDlgDllApp::InitInstance()
{
    CWinApp::InitInstance();

    OleInitialize(NULL); // эту строку наверно надо убрать. Пока еще не пробовал без неё. 

    if (!AfxOleInit())
    {        
        AfxMessageBox(_T("OLE не работает! "));
                           return FALSE;
    }

    AfxEnableControlContainer();
    
}



7. Компилируем и вроде все готово.

вот так я вызываю этот метод из Dll, не в тему, но вдруг будет нужно.

Код

INSTANCE hDll = ::LoadLibrary(_T("DlgD2.dll"));
    
    if (!hDll)
    {
        
        MessageBox(NULL, "Dll Не найдена", "MyDebug ", MB_ICONERROR|MB_OK);
        
        FreeLibrary(hDll);
        return;
    }

typedef void (CALLBACK *LPFNDLLFUNC1)(void);


LPFNDLLFUNC1 lp_Test;

    lp_Test = (LPFNDLLFUNC1)(GetProcAddress(hDll, "Test"));
    if (!lp_Test)
    {    
        FreeLibrary(hDll);
         MessageBox(NULL, "Метод в Dll не найден", "MyDebug ", MB_ICONERROR|MB_OK);
                
    }    
    
    lp_Test(); //вызов нашей функции.



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




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


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

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