Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как в CPropertySheet добавить CPropertyPage из DLL 
V
    Опции темы
Bukmop
  Дата 1.6.2006, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Помогите в CPropertySheet добавить CPropertyPage из DLL

TestEXE.cpp
Код

#include "TestDLL.h"

{
CPropertySheet sheet("Property Sheet");
CTest1 p1;
sheet.AddPage(&p1);
sheet.DoModal();
}


TestDLL.h
Код

class AFX_EXT_CLASS CTest1 : public CPropertyPage
{
DECLARE_DYNAMIC(CTest1)
DECLARE_MESSAGE_MAP()
public:
CTest1() : CPropertyPage( CTest1::IDD ) {};
enum { IDD = IDD_TEST1 };
virtual BOOL OnInitDialog();
};

TestDLL.cpp
Код

#include "TestDLL.h"

IMPLEMENT_DYNAMIC(CTest1, CPropertyPage)
BEGIN_MESSAGE_MAP(CTest1, CPropertyPage)
END_MESSAGE_MAP()

BOOL CTest1::OnInitDialog()
{
CPropertyPage::OnInitDialog();
...
return(TRUE);
}

TestDLL.rc
Код

IDD_TEST1 DIALOGEX 0, 0, 270, 170
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Test-1"
FONT 8, "MS Sans Serif"
BEGIN
    CTEXT           "",IDC_TEXT,10,10,250,12
END
    

Это сообщение отредактировал(а) Bukmop - 1.6.2006, 18:14
PM MAIL   Вверх
DeadSoul
Дата 1.6.2006, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Единственная проблема там - ресурсы. Вот пример для родительского диалога в ехе, а child-ового в dll
Код

HINSTANCE hInstExe = AfxGetResourceHandle(); 
AfxSetResourceHandle(::GetModuleHandle(“mdlldll”));
pDlg2->Create(IDD_DLG2, pDlg );
AfxSetResourceHandle(hInstExe);


Делай аналогично 


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
Bukmop
Дата 1.6.2006, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Не совсем понял, куда это девать.
Поэтому уточнил задачу.
 
PM MAIL   Вверх
Earnest
Дата 1.6.2006, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



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

Нет практически никакой разницы, где определен класс-страница - в другой DLL или в том модуле, где создается PropertySheet. Достаточно просто сделать класс экспортируемым. Можно не весь класс, а только конструктор и деструктор. Дальше все, как у тебя в коде.

Экспортировать можно 2 способами:

1) __declspec( dllimport )\__declspec( dllexport ):
экспортируемая сущность должна быть объявлена в своем модуле как __declspec( dllexport ),
а в чужом - как __declspec( dllimport )
Проще всего это достигается макросом:

Код

#ifdef _TESTDLL
   #define TEST_API __declspec(dllexport)
#else
   #define TEST_API __declspec(dllimport)
#endif

class CTestPropPaget: public CPropertyPage
{
public:
   TEST_API CTestPropPage();
   TEST_API ~CTestPropPage();

};

// или, чтобы экспортировать весь класс

class TEST_API CTestPropPage: public CPropertyPage
{
public:
   CTestPropPage();
   ~CTestPropPage();
};


Макросимвол _TESTDLL нужно определить для всего проекта TestDll (в свойствах проекта)

2) def - файл. Просто поместить имена всех нужных функций в def-файл.
На самом деле это не очень просто, т.к. имена должны быть декорированными, т.е. такими, как их видит линкер. Но можно сделать так: сначала ничего никуда не пишем, а просто пытаемся собрать приложение. Линкер будет орать насчет неразрешенных ссылок. Акуратно копируем имена, которые он хочет, прямо из сообщения об ошибке, и помещаем их в def- файл. Выглядеть будет примерно так:

Код

LIBRARY      "TestDLL"
EXPORTS
?GetThisMessageMap@CTestPropPage@@KGPBUAFX_MSGMAP@@XZ


Второй способ плох тем, что при малейшем изменении интерфейса экспортируемых функций нужно менять запись в def-файле. Даже просто при изменении доступа с public на, скажем, protected...
Сдругой стороны, есть сущности, которые иначе как через def-файл не проэкспортируешь.
  

Это сообщение отредактировал(а) Earnest - 1.6.2006, 17:16


--------------------
...
PM   Вверх
Bukmop
Дата 1.6.2006, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Подобное, я уже пробовал, используя встроенный в MFC макрос AFX_EXT_CLASS. Но я понял так, что это для экспорта класса на стадии компиляции, а не выполнения. Короче, линкер по-прежнему ругался. 
PM MAIL   Вверх
DeadSoul
Дата 1.6.2006, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Earnest @  1.6.2006,  17:13 Найти цитируемый пост)
DeadSoul имел в виду случай, когда ресурс страницы загружается из другого модуля, у тебя же там весь код, как я понимаю

Там весь код включая и PropertySheet? 


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
Earnest
Дата 1.6.2006, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Значит, что-то ты сделал неправильно.
Если DLL одна, то вполне можно обойтись макросом AFX_EXT_CLASS, только чтобы он заработал, DLL должна быть создана как ExtensionDLL (кроме всего прочего, в проект добавляется макросимвол _AFXEXT, а без него, конечно, не получится).

В общем, опиши, что ты сделал, и какие ошибки дает линкер.

Добавлено @ 18:19 
Цитата(DeadSoul @  1.6.2006,  19:14 Найти цитируемый пост)
Там весь код включая и PropertySheet?  

Нет, как я понимаю, код Property Sheet находится в EXE.
 


--------------------
...
PM   Вверх
Bukmop
Дата 1.6.2006, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Earnest, ты как всегда всё правильно понимаешь, а я очень извиняюсь за ложную информацию (сам уже начал путаться в результатах попыток, голова уже плохо соображает). В том случае всё скомпилировалось, но вытащить страницу не получилось.
Делал так:
Код

HINSTANCE hInst1=::LoadLibrary("Test1.dll");
if(hInst1)
    {
    CTest1* p1=(CTest1*)::GetProcAddress(hInst1,"СTest1");
    if(p1)
        sheet.AddPage(p1);
    }

Получал p1=NULL;

А если бы делал всё правильно – то всё бы работало (чудес-то не бывает).   

Это сообщение отредактировал(а) Bukmop - 1.6.2006, 19:08
PM MAIL   Вверх
Earnest
Дата 1.6.2006, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Да уж, зову не знамо кого... smile  А оно и не отзывается почему-то...
Вообще-то при такой связи с DLL ее лучше не динамически подключать, а прямо к проекту, чтобы еще линкер все ссылки разрешил.
Так ты разобрался в конце концов? 


--------------------
...
PM   Вверх
Bukmop
Дата 1.6.2006, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я тычусь как слепой котёнок, т.к. не понимаю, как правильно сделать, сижу и перебираю все мыслимые и немыслимые варианты (пока впустую).
Вот последний:
DLL
Код

CTest1* AFX_EXT_DATA pTest1=NULL;

DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
    pTest1=new CTest1;
    }
}

EXE
Код

HINSTANCE hInst1=::LoadLibrary("Test1.dll");
CTest1* p1=(CTest1*)::GetProcAddress(hInst1,"pTest1");

 
Благодарю за терпение, по себе знаю как трудно с такими... Но мне уже начинает казаться, что я хочу невозможного. 

Это сообщение отредактировал(а) Bukmop - 1.6.2006, 19:25
PM MAIL   Вверх
DeadSoul
Дата 1.6.2006, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Bukmop, так ответь на простые вопросы:
1. Где находится твой ProperySheet( dll\exe )?
2. Где находится PropertPage( dll\exe )?
3. Где ты создаешь твой PropertySheet( dll\exe )?


P.S. LoadLibrary тут не нужен 


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
Bukmop
Дата 1.6.2006, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



DeadSoul
1. exe
2. dll
3. exe
 
P.S. Смысл: Есть dll-ки - есть странички. Нет dll-ек - нет страничек. Изменились свойства dll-ек - не нужно трогать exe-ник.
   

Это сообщение отредактировал(а) Bukmop - 1.6.2006, 19:43
PM MAIL   Вверх
DeadSoul
Дата 1.6.2006, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



4. Как ты получаешь доступ к классам\функция в dll
- прописываешь в exe все необходимые *.h+*.lib
- LoadLibrary+GetProcAddress 


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
Bukmop
Дата 1.6.2006, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



4. Пытался - LoadLibrary+GetProcAddress.

lib мне не подходит, т.к. при изменении dll-ки придётся перекомпилировать exe-шник.
 

Это сообщение отредактировал(а) Bukmop - 1.6.2006, 21:01
PM MAIL   Вверх
Earnest
Дата 2.6.2006, 06:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Так бы сразу и сказал, что тебе обязательно нужно загружать DLL динамически.
Тогда действительно, LoadLibrary + GetProcAddress. НО: получить через GetProcAddress можно только то, что есть в таблице экспорта. Поскольку экспортировать придется через def-файл, то с классами возиться сложно (надо ведь декорированные имена записывать для всех функций),
Поэтому делаем так:
1) К EXE ничего не подключаем (h-файла с описанием страницы), придется ему довольствоваться интерфейсом CPropertyPage.
2) В DLL создаем функцию CPropertyPage* CreatePage(/* нужные параметры */). Причем объявляем ее как extern "C", чтобы не мучиться с именами. И записываем в def-файл. Вот только не помню, это будет просто CreatePage или _CreatePage, нужно уточнить. Впрочем, с неправильной записью в def-файле DLL не соберется.Еще можно уточнить имя с помощью map-файла.
3) Дальше все как ты делал, GetProcAddress c тем именем, что записано в def.
4) Только теперь у тебя выделена память под страницу, поэтому не забудь ее удалить после DoModal.
5) Не уверена, что по delete будет вызван правильный деструктор. Я бы проверила, поставив туда точку прерывания...

 


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


 




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


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

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