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

Ваш аккаунт

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

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

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

Чтение ресурсов в Dll. Нужен совет!

1.6K
01 декабря 2004 года
GDragon
67 / / 11.10.2002
Всем привет.
Значится так, была у меня прога (MDI), в главном окне которой слева торчал ControlBar, который содержал TreeCtrl и ListCtrl, причем TreeCtrl был основательно напичкан кодом, имел иконки и вызывал к жизни три разных диалога.
Но тут я осознал, что Бар выполняет чисто вспомогательные функции, перегружает проект кодом, возможно я захочу его отключить или переделать и т. п. Короче, созрела идея задействовать Бар как плагин. Я перегнал код в MFC DLL, DLL динамически присоединил к приложению. Связь с плагином организовал по типу COM, т. е. из приложения во внешнюю функцию DLL передается указатель на унифицированный базовый класс (читай интерфейс), в этой функции создается объект класса, порожденного от базового, и указатель возвращается в программу, которая юзает готовый объект (активирует плагин). ControlBar появляется, все Ок, но ни иконок ни диалогов, которые, естественно, хранятся в ресурсах DLL, нет. Теперь внимание вопрос: как мне заставить прогу когда нужно хавать ресурсы из DLL, а когда нужно - из EXE?
P.S. До этого иконы грузились так
AfxGetApp()->LoadIgon(...)
Все диалоги - порождения CDialog (что, впрочем, естественно :)).
3
01 декабря 2004 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by GDragon
Всем привет.
Значится так, была у меня прога (MDI), в главном окне которой слева торчал ControlBar, который содержал TreeCtrl и ListCtrl, причем TreeCtrl был основательно напичкан кодом, имел иконки и вызывал к жизни три разных диалога.
Но тут я осознал, что Бар выполняет чисто вспомогательные функции, перегружает проект кодом, возможно я захочу его отключить или переделать и т. п. Короче, созрела идея задействовать Бар как плагин. Я перегнал код в MFC DLL, DLL динамически присоединил к приложению. Связь с плагином организовал по типу COM, т. е. из приложения во внешнюю функцию DLL передается указатель на унифицированный базовый класс (читай интерфейс), в этой функции создается объект класса, порожденного от базового, и указатель возвращается в программу, которая юзает готовый объект (активирует плагин). ControlBar появляется, все Ок, но ни иконок ни диалогов, которые, естественно, хранятся в ресурсах DLL, нет. Теперь внимание вопрос: как мне заставить прогу когда нужно хавать ресурсы из DLL, а когда нужно - из EXE?
P.S. До этого иконы грузились так
AfxGetApp()->LoadIgon(...)
Все диалоги - порождения CDialog (что, впрочем, естественно :)).



Используй
HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
где первый параметр - значение, которое возвращает LoadLibrary, т.е. HMODULE

1.6K
01 декабря 2004 года
GDragon
67 / / 11.10.2002
Цитата:
Originally posted by Green


Используй
HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
где первый параметр - значение, которое возвращает LoadLibrary, т.е. HMODULE


Я конечно могу передавать при инициализации плагина ему его же собственный HMODULE, правда не очень изяШное решение. Неужели нельзя получить HMODULE при инициализации библиотеки в самой библиотеке? Но это даже не самая проблема. Самая проблема - как заставить корректно создаваться диалоги. Диалоги создаются в DLL, а ресурсы пытаются читать из главного модуля, где их, естественно, нет!

3
01 декабря 2004 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by GDragon

Я конечно могу передавать при инициализации плагина ему его же собственный HMODULE, правда не очень изяШное решение. Неужели нельзя получить HMODULE при инициализации библиотеки в самой библиотеке? Но это даже не самая проблема. Самая проблема - как заставить корректно создаваться диалоги. Диалоги создаются в DLL, а ресурсы пытаются читать из главного модуля, где их, естественно, нет!



Есть у меня один секретный способ. :D
Только никому!... :)

 
Код:
// returns the HMODULE that contains this function
HMODULE GetModuleBaseAddress()
{
    MEMORY_BASIC_INFORMATION mbi;
    return ((::VirtualQuery(GetModuleBaseAddress, &mbi, sizeof(mbi)) != 0) ?
        (HMODULE) mbi.AllocationBase : NULL);
}
1.6K
01 декабря 2004 года
GDragon
67 / / 11.10.2002
Цитата:
Originally posted by Green


Есть у меня один секретный способ. :D
Только никому!... :)
 
Код:
// returns the HMODULE that contains this function
HMODULE GetModuleBaseAddress()
{
    MEMORY_BASIC_INFORMATION mbi;
    return ((::VirtualQuery(GetModuleBaseAddress, &mbi, sizeof(mbi)) != 0) ?
        (HMODULE) mbi.AllocationBase : NULL);
}


Спасибо за подсказку, но где брать GetModuleBaseAddress?
Ага, врубился. Хитрая конструкция получается. Только что пробовал так:
HMODULE hModule = (::VirtualQuery(this, &mbi, sizeof(mbi)) != 0) ? (HMODULE) mbi.AllocationBase : NULL;
(Вызывается из класса)
Нифига не вышло.

О! Есть, заработало! Спасибо. Теперь буду пытаться оживлять диалоги. А може у тебя и на энтот случай решение есть? Никому не скажу, чесслово :D

3
01 декабря 2004 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by GDragon

Спасибо за подсказку, но где брать GetModuleBaseAddress?
Ага, врубился. Хитрая конструкция получается. Только что пробовал так:
HMODULE hModule = (::VirtualQuery(this, &mbi, sizeof(mbi)) != 0) ? (HMODULE) mbi.AllocationBase : NULL;
(Вызывается из класса)
Нифига не вышло.

О! Есть, заработало! Спасибо. Теперь буду пытаться оживлять диалоги. А може у тебя и на энтот случай решение есть? Никому не скажу, чесслово :D



А какая проблема с диалогами?
Если ты их создаешь в DLL, то в основной модуль (exe) передаешь, наверное, HWND или указатель на некоторый объект, связанный с окном диалога?
Так в чем проблема?

1.6K
01 декабря 2004 года
GDragon
67 / / 11.10.2002
Цитата:
Originally posted by Green


А какая проблема с диалогами?
Если ты их создаешь в DLL, то в основной модуль (exe) передаешь, наверное, HWND или указатель на некоторый объект, связанный с окном диалога?
Так в чем проблема?


Диалоги создаются в DLL на основе ресурсов:
CDialog myDialog;
myDialog.Create(IDD_MYDIALOG, ... );
Ну а поскольку Create рвется читать ресурсы из EXE, где их нет, то и диалог не создается.
Ладно, подумаю над этим завтра. X)-

3
01 декабря 2004 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by GDragon

Диалоги создаются в DLL на основе ресурсов:
CDialog myDialog;
myDialog.Create(IDD_MYDIALOG, ... );
Ну а поскольку Create рвется читать ресурсы из EXE, где их нет, то и диалог не создается.
Ладно, подумаю над этим завтра. X)-



Ох уж этот MFC... :x
Вообще-то в методе CDialog::Create происходит перебор всех загруженных модулей на предмет поиска необходимого ресурса (см. AfxFindResourceHandle в dllinit.cpp), но видимо не совсем корректно.

Я бы добавил такие методы

Код:
BOOL CBaseDialog::Create(HINSTANCE hInst, LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)
{
    HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
    HGLOBAL hTemplate = LoadResource(hInst, hResource);
    BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst);
    FreeResource(hTemplate);

    return bResult;
}

BOOL CBaseDialog::Create(HINSTANCE hInst, UINT nIDTemplate, CWnd* pParentWnd = NULL)
{ return Create(hInst, MAKEINTRESOURCE(nIDTemplate), pParentWnd); }
831
02 декабря 2004 года
S_T
117 / / 23.10.2002
Цитата:
Originally posted by GDragon

Диалоги создаются в DLL на основе ресурсов:
CDialog myDialog;
myDialog.Create(IDD_MYDIALOG, ... );
Ну а поскольку Create рвется читать ресурсы из EXE, где их нет, то и диалог не создается.
Ладно, подумаю над этим завтра. X)-



В MFC есть такая функция (глобальная) AfxSetResourceHandle(HINSTANCE) - после того, как ты вызовишь ее с нужным HMODULE (для Exe или Dll), то все MFC'шные функции (будь то CDialog::Create, или CString::LoadString итп) будут грузить себя из ресурсов указанного HMODULE.
Так что перед созданием диалога, попробуй поиграться с этой функцией (не стоит забывать все возвращать на место).

831
02 декабря 2004 года
S_T
117 / / 23.10.2002
И еще, раз уж у вас так раскиданы ресурсы (EXE использует ресурсы из DLL) - то лучше создать отдельную DLL'ку с ресурсами (из всех модулей), при этом не забыть отрубить линковку ресурсов во всех модулях.

А затем на InitInstance приложения сделать LoadLibrary для этой ресурсной DLL'ки (то есть не линковать ее статически), и сразу же вызвать AfxSetResourceHandle(HMODULE ресурсной DLL).
Тогда выиграем следующее:
1. Из любого модуля можно пользовать любые ресурсы из всего приложения.
2. Лего настраивается локализация (переводишь все ресурсы на другой язык, компилишь ресурсную DLL'ку с другим именем - и уже пользователю можно опционально задавать язык, на котором будет его приложение)
1.6K
02 декабря 2004 года
GDragon
67 / / 11.10.2002
Цитата:
Originally posted by S_T
И еще, раз уж у вас так раскиданы ресурсы (EXE использует ресурсы из DLL) - то лучше создать отдельную DLL'ку с ресурсами (из всех модулей), при этом не забыть отрубить линковку ресурсов во всех модулях.

А затем на InitInstance приложения сделать LoadLibrary для этой ресурсной DLL'ки (то есть не линковать ее статически), и сразу же вызвать AfxSetResourceHandle(HMODULE ресурсной DLL).
Тогда выиграем следующее:
1. Из любого модуля можно пользовать любые ресурсы из всего приложения.
2. Лего настраивается локализация (переводишь все ресурсы на другой язык, компилишь ресурсную DLL'ку с другим именем - и уже пользователю можно опционально задавать язык, на котором будет его приложение)


Спасибо за советы, сейчас буду пробовать.
А создавать отдельную DLL с ресурсами не желательно по определению. Вся суть переделки первой версии программы как раз сводилась к тому, чтобы она хавала унифицированные плагины, коих может быть n-ное количество, и не плакала, если вдруг чего не найдет. Плагин добавляется простым переписыванием DLL в специальную папку. Т. е. до того, как прога найдет DLL в папке Plugins, она вообще не подозревает о его существовании. В такой ситуации общие ресурсы - не лучшее решение.

1.6K
02 декабря 2004 года
GDragon
67 / / 11.10.2002
Цитата:
Originally posted by S_T


В MFC есть такая функция (глобальная) AfxSetResourceHandle(HINSTANCE) - после того, как ты вызовишь ее с нужным HMODULE (для Exe или Dll), то все MFC'шные функции (будь то CDialog::Create, или CString::LoadString итп) будут грузить себя из ресурсов указанного HMODULE.
Так что перед созданием диалога, попробуй поиграться с этой функцией (не стоит забывать все возвращать на место).


Отлично! Все заработало, когда я переопределил DoModal следующим образом:
int CBaseCreateFolderDlg::DoModal()
{
HMODULE hMainModule = (HMODULE)AfxGetResourceHandle();
AfxSetResourceHandle(GetModuleBaseAddress());

int nResult = CDialog::DoModal();

AfxSetResourceHandle(hMainModule);
return nResult;
}
Всем спасибо! :)

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог