LoadLibrary и ComCtl32.dll
От: Аноним  
Дата: 03.10.13 19:03
Оценка:
Есть простая задача: создать progress bar control на главном окне подключив ConCtl32.dll динамически с помощью LoadLibrary().

В сети есть достаточно примеров линковки с ComCtl32.lib и вызовом InitCommonControlEx() через таблицу импорта. Эти примеры прекрасно работают.

Тем не менее, попытки сделать то же самое с помощью LoadLibrary() приводят к тому, что вызов InitCommonControlEx() как будто не регистрирует нужные классы окон, хотя сама функция возвращает TRUE.

Код выглядит так:

    INITCOMMONCONTROLSEX initCtrls;

    HMODULE lib;
    WNDCLASSEX xClass;

    typedef VOID (WINAPI *LPFN_INITCOMMONCONTROLS)(VOID);
    typedef BOOL (WINAPI *LPFN_INITCOMMONCONTROLSEX)(LPINITCOMMONCONTROLSEX);

    LPFN_INITCOMMONCONTROLS  InitCommonControlsPtr;
    LPFN_INITCOMMONCONTROLSEX  InitCommonControlsExPtr;

    Check((lib = LoadLibrary(".\\comctl32.dll")) != NULL, "LoadLibrary");

    InitCommonControlsPtr = (LPFN_INITCOMMONCONTROLS)GetProcAddress(lib, "InitCommonControls");
    Check(InitCommonControlsPtr != NULL, "InitCommonControls");

    InitCommonControlsExPtr = (LPFN_INITCOMMONCONTROLSEX)GetProcAddress(lib, "InitCommonControlsEx");
    Check(InitCommonControlsExPtr != NULL, "InitCommonControlsEx");

    InitCommonControlsPtr();

    initCtrls.dwSize = sizeof(initCtrls);
    initCtrls.dwICC = (ICC_PROGRESS_CLASS | ICC_BAR_CLASSES | ICC_WIN95_CLASSES);
    Check(InitCommonControlsExPtr(&initCtrls), "InitCommonControlsExPtr");

    Check(GetClassInfoEx(lib, PROGRESS_CLASS, &xClass), "GetClassInfoEx");


Здесь Check() -- это функция, которая проверяет соблюдение условия (первый аргумент) и генерирует диагностику в случае ошибки.

Последний вызов заканчивается ошибкой с кодом 0x583 ("Класс не существует").

Может быть, есть что-то особенное, что нужно знать о таком способе использования ComCtl32.dll ?
Re: LoadLibrary и ComCtl32.dll
От: okman Беларусь https://searchinform.ru/
Дата: 03.10.13 19:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть простая задача: создать progress bar control на главном окне подключив ConCtl32.dll динамически с помощью LoadLibrary().


А>В сети есть достаточно примеров линковки с ComCtl32.lib и вызовом InitCommonControlEx() через таблицу импорта. Эти примеры прекрасно работают.


А>Тем не менее, попытки сделать то же самое с помощью LoadLibrary() приводят к тому, что вызов InitCommonControlEx() как будто не регистрирует нужные классы окон, хотя сама функция возвращает TRUE.


Видимо, в манифесте должна быть ссылка на нужную версию common controls.
Имеется в виду вот это:
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
Re: LoadLibrary и ComCtl32.dll
От: MasterZiv СССР  
Дата: 03.10.13 19:13
Оценка:
Здравствуйте, Аноним, Вы писали:


А> InitCommonControlsPtr();

А> initCtrls.dwSize = sizeof(initCtrls);
А> initCtrls.dwICC = (ICC_PROGRESS_CLASS | ICC_BAR_CLASSES | ICC_WIN95_CLASSES);
А> Check(InitCommonControlsExPtr(&initCtrls), "InitCommonControlsExPtr");


А>Может быть, есть что-то особенное, что нужно знать о таком способе использования ComCtl32.dll ?


Зачем вызывать инициализацию ДВАЖДЫ ?
InitCommonControls и InitCommonControlsEx взаимозаменяемы.

К тому же:

InitCommonControls function
Registers and initializes certain common control window classes. This function is obsolete. New applications should use the InitCommonControlsEx function.

Re[2]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 03.10.13 19:17
Оценка:
Здравствуйте, okman, Вы писали:

O>Видимо, в манифесте должна быть ссылка на нужную версию common controls.


Гм. Добавление манифеста действительно приводит к тому, что классы регистрируются. Однако это не решает исходной проблемы, поскольку смысл использования LoadLibrary() с указанием полного пути к библиотеке именно в том, чтобы избежать манифестов и использовать ту версию библиотеки, которая нашлась в системе.

Может быть, есть способ написать манифест так, чтобы ComCtrl32.dll версии 6 использовалась только тогда, когда она доступна в системе, а в остальных случаях использовалась версия 5? Это решило бы дело.
Re[2]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 03.10.13 19:25
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Зачем вызывать инициализацию ДВАЖДЫ ?

MZ>InitCommonControls и InitCommonControlsEx взаимозаменяемы.

1) Я так понимаю, что это не имеет отношения к исходному вопросу?

2) Вызов InitCommonControls() добавлен "на всякий случай", исходя из того, что во времена до InitCommonControlsEx() именно вызов InitCommonControls() обеспечивал инициализацию библиотеки.

3) InitCommonControls() конечно же не заменяет InitCommonControlsEx().
Re[3]: LoadLibrary и ComCtl32.dll
От: okman Беларусь https://searchinform.ru/
Дата: 03.10.13 19:25
Оценка:
Здравствуйте, rtiuni, Вы писали:

R>Может быть, есть способ написать манифест так, чтобы ComCtrl32.dll версии 6 использовалась только тогда, когда она доступна в системе, а в остальных случаях использовалась версия 5? Это решило бы дело.


А в каких системах, например, отсутствует шестая версия comctl32.dll ?
Re[4]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 03.10.13 19:42
Оценка:
Здравствуйте, okman, Вы писали:

O>А в каких системах, например, отсутствует шестая версия comctl32.dll ?


Может быть, на свежевыставленной XP без SP1 ?

Вы правы, нужно озадачиться этим вопросом. Может быть, и нет никакой проблемы.
Re[5]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 04.10.13 07:06
Оценка:
Здравствуйте, rtiuni, Вы писали:

R>Вы правы, нужно озадачиться этим вопросом. Может быть, и нет никакой проблемы.


http://www.geoffchappell.com/studies/windows/shell/comctl32/history/index.htm?tx=14

Получается, что в XP может быть версия 5.82, поэтому действительно нужно уметь поддерживать обе версии библиотеки и проблема все еще актуальна.
Re[6]: LoadLibrary и ComCtl32.dll
От: okman Беларусь https://searchinform.ru/
Дата: 04.10.13 07:11
Оценка:
Здравствуйте, rtiuni, Вы писали:

R>http://www.geoffchappell.com/studies/windows/shell/comctl32/history/index.htm?tx=14


R>Получается, что в XP может быть версия 5.82, поэтому действительно нужно уметь поддерживать обе версии библиотеки и проблема все еще актуальна.


Ну а что Вас смущает ?
Если верить приведенной таблице "версия comctl32.dll — релиз Windows/IE", шестая
comctl32.dll есть в Windows XP, начиная с RTM-версии.
Re[3]: LoadLibrary и ComCtl32.dll
От: Pavel Dvorkin Россия  
Дата: 04.10.13 07:29
Оценка: 1 (1)
Здравствуйте, rtiuni, Вы писали:

R>2) Вызов InitCommonControls() добавлен "на всякий случай", исходя из того, что во времена до InitCommonControlsEx() именно вызов InitCommonControls() обеспечивал инициализацию библиотеки.


InitCommonControls ничего не инициализировала вообще. Ее код состоял из одной команды ret. Просто вызов этой функции приводил к тому, что commctl32 оказывалась в списке импорта EXE и неявно загружалась при старте процесса. Иначе она могла бы и не загрузиться при старте процесса, а потом (намного позже) не создался бы диалог с common controls — их классы именно commctl32 регистрирует.
With best regards
Pavel Dvorkin
Re[7]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 04.10.13 07:41
Оценка:
Здравствуйте, okman, Вы писали:

O>Ну а что Вас смущает ?

O>Если верить приведенной таблице "версия comctl32.dll — релиз Windows/IE", шестая
O>comctl32.dll есть в Windows XP, начиная с RTM-версии.

Упс. А я прочитал таблицу так, что в XP может быть только пятая версия. Спасибо.
Re[8]: LoadLibrary и ComCtl32.dll
От: okman Беларусь https://searchinform.ru/
Дата: 04.10.13 07:42
Оценка:
Здравствуйте, rtiuni, Вы писали:

R>Упс. А я прочитал таблицу так, что в XP может быть только пятая версия. Спасибо.


В любом случае стоит проверить. Хотя Windows XP без SP еще попробуй достать...
Re[4]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 04.10.13 07:44
Оценка: -1
Здравствуйте, Pavel Dvorkin, Вы писали:

R>>2) Вызов InitCommonControls() добавлен "на всякий случай", исходя из того, что во времена до InitCommonControlsEx() именно вызов InitCommonControls() обеспечивал инициализацию библиотеки.


PD>InitCommonControls ничего не инициализировала вообще. Ее код состоял из одной команды ret. Просто вызов этой функции приводил к тому, что commctl32 оказывалась в списке импорта EXE и неявно загружалась при старте процесса. Иначе она могла бы и не загрузиться при старте процесса, а потом (намного позже) не создался бы диалог с common controls — их классы именно commctl32 регистрирует.


Да, InitCommonControls() была и остается пустой, но ее вызов приводил не просто к импорту ComCtl32.dll, а к ее фактической загрузке в момент самого вызова, что означает вызов DllMain() и регистрацию классов ICC_WIN95_CLASSES. Так что не путайте, пожалуйста, себя и других.
Re[9]: LoadLibrary и ComCtl32.dll
От: rtiuni  
Дата: 04.10.13 07:46
Оценка:
Здравствуйте, okman, Вы писали:

R>>Упс. А я прочитал таблицу так, что в XP может быть только пятая версия. Спасибо.


O>В любом случае стоит проверить. Хотя Windows XP без SP еще попробуй достать...


Вот именно. Мой экземпляр уже включает SP2, поэтому сам проверить не могу.
Re[5]: LoadLibrary и ComCtl32.dll
От: Pavel Dvorkin Россия  
Дата: 04.10.13 13:11
Оценка:
Здравствуйте, rtiuni, Вы писали:

PD>>InitCommonControls ничего не инициализировала вообще. Ее код состоял из одной команды ret. Просто вызов этой функции приводил к тому, что commctl32 оказывалась в списке импорта EXE и неявно загружалась при старте процесса. Иначе она могла бы и не загрузиться при старте процесса, а потом (намного позже) не создался бы диалог с common controls — их классы именно commctl32 регистрирует.


R>Да, InitCommonControls() была и остается пустой, но ее вызов приводил не просто к импорту ComCtl32.dll, а к ее фактической загрузке в момент самого вызова, что означает вызов DllMain() и регистрацию классов ICC_WIN95_CLASSES. Так что не путайте, пожалуйста, себя и других.


Никого я не путаю. То, что в результате загрзузки DLL вызовется DLLMain — полагаю, всем здесь хорошо известно. Косвенно я об этом сказал — "их классы именно commctl32 регистрирует". Естетсвенно, DLLMain их в конечном счете и регистрирует — больше просто некому.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.