Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Call to SystemParametersInfo() no longer works under Borland C++ Builder 7

58 views
Skip to first unread message

James O'Brien

unread,
Aug 5, 2008, 4:23:43 PM8/5/08
to
I have code which performs custom painting to a window's title
bar(non-client area). I recently migrated from "C++ Build v6" to "C++
Builder 2007" and calls to SystemParametersInfo() no longer work.


*********************
code sample
*********************

NONCLIENTMETRICS NCM;

ZeroMemory(&NCM, sizeof(NONCLIENTMETRICS));
NCM.cbSize = sizeof(NONCLIENTMETRICS);

SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(NONCLIENTMETRICS),
(PVOID)&NCM,
0);

After zeroing the NCM structure and assigning NCM.cbSize the correct value,
a call to SystemParametersInfo() has no effect. All data members in the NCM
structure are unchanged. This code works correctly under C++ Builder v6.

Any thoughts?

Thanks
James O'Brien


Remy Lebeau (TeamB)

unread,
Aug 5, 2008, 4:45:56 PM8/5/08
to

"James O'Brien" <obr...@niscnet.com> wrote in message
news:4898b6ce$1...@newsgroups.borland.com...

> I have code which performs custom painting to a window's title
> bar(non-client area). I recently migrated from "C++ Build v6" to
> "C++ Builder 2007" and calls to SystemParametersInfo() no
> longer work.

That is because the NONCLIENTMETRICS structure changed between those two
versions. BCB2007 has a newer Platform SDK, where the structure has an
additional iPaddedBorderWidth that did not exist yet in the SDK that BCB6
has. You are setting the cbSize member to the newer structure size, which
is not valid on the OS you are calling SystemParametersInfo() on. You have
to take the OS version into account when using API structures that have a
cbSize member, such as NONCLIENTMETRICS. This is clearly stated in the
documentation for NONCLIENTMETRICS:

http://msdn.microsoft.com/en-us/library/ms724506(VS.85).aspx

If the iPaddedBorderWidth member of the NONCLIENTMETRICS structure is
present, this structure is 4 bytes larger than for an application that is
compiled with _WIN32_WINNT less than or equal to 0x0502. For more
information about conditional compilation, see Using the Windows Headers
(http://msdn.microsoft.com/en-us/library/aa383745(VS.85).aspx).

Windows Server 2003 and Windows XP/2000: If an application that is
compiled for Windows Server 2008 or Windows Vista must also run on Windows
Server 2003 or Windows XP/2000, use the GetVersionEx function to check the
operating system version at run time and, if the application is running on
Windows Server 2003 or Windows XP/2000, subtract the size of the
iPaddedBorderWidth member from the cbSize member of the NONCLIENTMETRICS
structure before calling the SystemParametersInfo function.

In other words, you need to update your code to do something like the
following:

NONCLIENTMETRICS NCM = {0};
NCM.cbSize = sizeof(NONCLIENTMETRICS);

if( Win32MajorVersion < 6 )
{
NCM.cbSize -= 4;

// alternatively:
// NCM.cbSize = offsetof(NONCLIENTMETRICS, iPaddedBorderWidth);
}

SystemParametersInfo(SPI_GETNONCLIENTMETRICS, NCM.cbSize, (PVOID)&NCM,
0);


Gambit

Piet

unread,
Oct 2, 2008, 5:59:59 AM10/2/08
to
On Aug 5, 10:45 pm, "Remy Lebeau \(TeamB\)" <no.s...@no.spam.com>
wrote:

Hi
I had the same problem except that my code worked in debug mode but
not in release. I tried Gambit's trick but eventually found that the
structure size is correct as given by sizeof(). What's not correct is
that iPaddedBorderWidth is defined in release build but not in debug
build, indicating that WINVER >= 0x600 when checked in winuser.h
during release build. When I comment iPaddedBorderWidth out as below,
everything is fine. I now have a solution that's ok for me, but I
don't understand where the incorrect WINVER comes from.

#if(WINVER >= 0x0600)
// int iPaddedBorderWidth;
#endif /* WINVER >= 0x0600 */
} NONCLIENTMETRICSA, *PNONCLIENTMETRICSA, FAR* LPNONCLIENTMETRICSA;

Piet

0 new messages