Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

SystemParametersInfo with SPI_GETNONCLIENTMETRICS may fail

Оказывается, на версиях всеми любимой OS Windows ниже 6 (XP/2003) вызов функции SystemParametersInfo проваливается, если в поле cbSize структуры NONCLIENTMETRICS указан размер больше, чем нужно. Посмотрим на структуру NONCLIENTMETRICS:

typedef struct tagNONCLIENTMETRICSW
{
    UINT    cbSize;
    int     iBorderWidth;
    int     iScrollWidth;
    int     iScrollHeight;
    int     iCaptionWidth;
    int     iCaptionHeight;
    LOGFONTW lfCaptionFont;
    int     iSmCaptionWidth;
    int     iSmCaptionHeight;
    LOGFONTW lfSmCaptionFont;
    int     iMenuWidth;
    int     iMenuHeight;
    LOGFONTW lfMenuFont;
    LOGFONTW lfStatusFont;
    LOGFONTW lfMessageFont;
#if(WINVER >= 0x0600)
    int     iPaddedBorderWidth;
#endif /* WINVER >= 0x0600 */
}   NONCLIENTMETRICSW, *PNONCLIENTMETRICSW, FAR* LPNONCLIENTMETRICSW;

Правильный код:

NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS), 0 };
#if (WINVER >= 0x0600)
OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO), 0 };
VERIFY(GetVersionEx(&osvi));
if (osvi.dwMajorVersion < 6) {
    ncm.cbSize -= sizeof(int);
}
#endif
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) {
    _defaultLogFont = ncm.lfMessageFont;
}

6 коммент.:

Анонимный комментирует...

Низкий поклон и спасибо за пример

Анонимный комментирует...

You've done a great service. This has been bugging me for over a week. It was really crazy because GetLastError() was returning 0 when SystemParametersInfo() was returning 0.

Анонимный комментирует...

Обязательно схожу поставлю автору свечку в церковь. :)

Анонимный комментирует...

Спасибо! Очень помогло.

Анонимный комментирует...

Автору респект. Проблемма обозначилась при переходе с VS6 на VC 2010.

Unknown комментирует...

Спасибо большое.

Отправить комментарий

Copyright 2007-2011 Chabster