Windows предварительно загружает ComCtrl32.dll в приложение? - PullRequest
4 голосов
/ 04 ноября 2010

Я столкнулся с ситуацией, когда мне известен код

. Я создал приложение MFC в Visual Studio 2008, которое генерирует значок в трее и некоторые уведомления.Я читал, что могу использовать другую структуру NOTIFYICONDATA для Windows Vista, чем для Windows XP, установив свойство cbSize структуры для ее инициализации.Я также читал, что я могу использовать LoadIconMetric в Windows Vista, чтобы загрузить свой значок для уведомления, тогда как в Windows XP эта функция мне не доступна, и я должен использовать LoadIcon.

Вмое приложение, я установил следующее:

#ifndef WINVER
#define WINVER 0x0600 // Vista
#endif

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600 // Vista
#end#if

#ifndef _WIN32_WINDOWS
#define _WIN32_WINDOWS 0x0600 // Vista
#endif

#ifndef _WIN32_IE
#define _WIN32_IE 0x0700
#endif

Я компилирую и связываю с Windows 7 SDK на компьютере с Windows 7 x64 в Visual Studio 2008. Мой тест для WindowsVista или выше выглядит следующим образом(прямо из MSDN):

static BOOL IsWinVistaOrLater()
{
    // Initialize the OSVERSIONINFOEX structure.
    OSVERSIONINFOEX osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    osvi.dwMajorVersion = 6;
    osvi.dwMinorVersion = 1;

    // Initialize the condition mask.
    DWORDLONG dwlConditionMask = 0;
    VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);

    // Perform the test.
    return VerifyVersionInfo(&osvi, 
            VER_MAJORVERSION | VER_MINORVERSION,
            dwlConditionMask);
}

Теперь вот интересная часть.Я использую IsWinVistaOrLater, чтобы определить, должен ли я использовать LoadIconMetric или LoadIcon:

if (IsWinVistaOrLater())
{
    tnd_Happy.dwInfoFlags = NIIF_LARGE_ICON | tnd_Happy.dwInfoFlags;
    LoadIconMetric(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON_HAPPY), LIM_SMALL, &(tnd_Happy.hIcon));
} else {
    tnd_Happy.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDI_ICON_HAPPY)); // ICON RESOURCE ID
}

В XP это выдает сообщение «Ordinal 380 не найден в ComCtrl32.dll».Если я закомментирую звонок на LoadIconMetric, все будет хорошо (даже если все эти цели установлены на Vista).Windows пытается импортировать все вызовы функций независимо от пути кода времени выполнения?

Ответы [ 3 ]

10 голосов
/ 26 марта 2013

Просто чтобы помочь другим, кто может столкнуться с очень похожей проблемой.Я не мог заставить LoadIconMetric работать даже под Windows 7 с приложением шаблона WinApi Visual Studio C ++ 2010 Express.После добавления Comctl32.lib в зависимости и включения CommCtrl.h, он продолжает говорить: «Ordinal 380 не найден в ComCtrl32.dll».Мне было не очень понятно, что я пропустил, потому что я был совершенно незнаком с переключением версий таких компонентов.Спустя некоторое время я понял, что вот такие ценные источники для такой ситуации:

Common Control Versions

Я решил проблему, добавив эту строку перед включением CommCtrl.h (Обратите внимание, что мое приложение предназначено только для Windows Vista и более поздних версий):

// Need CommCtrl v6 for LoadIconMetric()
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

Оно создано из примера проекта Microsoft:

Пример значка уведомления - NotificationIcon.zip

7 голосов
/ 04 ноября 2010

Если вы настроите заголовочные файлы для Vista, то это позволит вам создавать приложения, которые не будут загружаться в более ранних версиях Windows.Вот почему правильная установка этого файла так важна.

Чтобы обойти вашу проблему:

  • Должно быть возможно использовать / DELAYLOAD включите comctl32.dll.Без / DELAYLOAD Windows будет пытаться импортировать все функции заранее (независимо от пути кода)

  • Сбросить заголовочный файл целевой версии на 0x0501 (XP).Теперь Windows автоматически предупредит вас, если вы попытаетесь использовать какие-либо дополнительные функции.Получите доступ к новой функциональности, используя LoadLibrary ("comctl32.dll") && GetProcAddress ("LoadIconMetric").Недостатком этого метода является то, что вы можете совершать новые вызовы через GetProcAddress, но структуры (если они изменились) будут старыми структурами.

Наконец, много comctl32.Возможности DLL - это хитрость: если у вас нет специально настроенных визуальных стилей 1018 *, тогда ваша версия comctl32.dll всегда должна быть версией 5.(Если у вас есть проект MFC, созданный в VS2005 или VS2008, это должно было быть сделано автоматически).Это означает, что можно установить WINVER в Vista, но затем вызовы ComCtl32 начинают давать сбои, потому что ComCtl32 версии 5 не понимает новые большие структуры.

3 голосов
/ 05 ноября 2010

Вместо LoadLibrary и GetProcAddress, предложенных Крисом, вы можете написать DLL-библиотеку с задержкой загрузки только для Vista, которая содержит весь код только для Vista, в то время как ваш основной проект по-прежнему ориентирован на XP. Тогда вам не нужно загружать код только для Vista, если выполнение не пройдет проверку версии Vista и не вызовет функции, экспортированные из DLL-кода кода Vista.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...