SystemParametersInfo (user32)
Last changed: -212.117.77.91

.
Summary

C# Signature:

[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);

[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref ANIMATIONINFO pvParam, uint fWinIni);

User-Defined Types:

SPI, ANIMATIONINFO

Notes:

None.

Tips & Tricks:

When using the SPI_GETANIMATION or SPI_SETANIMATION actions, the uiParam value must be set to (System.UInt32)Marshal.SizeOf(typeof(ANIMATIONINFO)).

Sample Code:

    // This code works for SPI_GETFOREGROUNDLOCKTIMEOUT, the above signature doesn't. (Ken)

    [DllImport("user32.dll", EntryPoint="SystemParametersInfo", SetLastError = true)]
    public static extern bool SystemParametersInfoGet(uint action, uint param, ref uint vparam,     uint init);

    [DllImport("user32.dll", EntryPoint="SystemParametersInfo", SetLastError = true)]
    public static extern bool SystemParametersInfoSet(uint action, uint param, uint vparam,     uint init);

    // get current lock timeout value
    uint timeout = 99;
    bool retVal = SystemParametersInfoGet(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref timeout, 0);
    // set current lock timeout value to 0, so focus can be grabbed
    SystemParametersInfoSet(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, 0);

SPI_GETNONCLIENTMETRICS is a good way to get user-defined preferences for fonts, colors, icons, etc. There is no other way to do this in .NET as far as I know!

    // We can overload this definition, since that's in effect what the unmanaged
    // API does anyway.
    [DllImport("user32", CharSet=CharSet.Auto)]
    private static extern int SystemParametersInfo(int uAction,
        int uParam, ref NONCLIENTMETRICS lpvParam, int fuWinIni);

    private const int LF_FACESIZE = 32;

    // A "logical font" used by old-school windows
    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
    private struct LOGFONT
    {
        public int lfHeight;
        public int lfWidth;
        public int lfEscapement;
        public int lfOrientation;
        public int lfWeight;
        public byte lfItalic;
        public byte lfUnderline;
        public byte lfStrikeOut;
        public byte lfCharSet;
        public byte lfOutPrecision;
        public byte lfClipPrecision;
        public byte lfQuality;
        public byte lfPitchAndFamily;

        /// <summary>
        /// <see cref="UnmanagedType.ByValTStr"/> means that the string
        /// should be marshalled as an array of TCHAR embedded in the
        /// structure.  This implies that the font names can be no larger
        /// than <see cref="LF_FACESIZE"/> including the terminating '\0'.
        /// That works out to 31 characters.
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
        public string lfFaceName;

        // to shut it up about the warnings
         public LOGFONT(string lfFaceName)
        {
            this.lfFaceName = lfFaceName;
                  lfHeight = lfWidth = lfEscapement = lfOrientation = lfWeight = 0;
                  lfItalic = lfUnderline = lfStrikeOut = lfCharSet = lfOutPrecision
                  = lfClipPrecision = lfQuality = lfPitchAndFamily = 0;
         }
    }

    private struct NONCLIENTMETRICS
    {
        public int cbSize;
        public int iBorderWidth;
        public int iScrollWidth;
        public int iScrollHeight;
        public int iCaptionWidth;
        public int iCaptionHeight;
        /// <summary>
        /// Since <see cref="LOGFONT"/> is a struct instead of a class,
        /// we don't have to do any special marshalling here.  Much
        /// simpler this way.
        /// </summary>
        public LOGFONT lfCaptionFont;
        public int iSMCaptionWidth;
        public int iSMCaptionHeight;
        public LOGFONT lfSMCaptionFont;
        public int iMenuWidth;
        public int iMenuHeight;
        public LOGFONT lfMenuFont;
        public LOGFONT lfStatusFont;
        public LOGFONT lfMessageFont;
    }

    private const int SPI_GETNONCLIENTMETRICS = 41;

OK, so here is how you query for the NONCLIENTMETRICS

    NONCLIENTMETRICS metrics = new NONCLIENTMETRICS();
    metrics.cbSize = Marshal.SizeOf(metrics);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, ref metrics, 0);

Now you can use the font info however you want. Here's how to return a GDI+ Font corresponding to the MessageBox font selected by the user. Note that the height is always negative and always returns "world" units.

    return new Font(Metrics.lfMessageFont.lfFaceName,
                    -Metrics.lfMessageFont.lfHeight,
            GraphicsUnit.World);

Alternative Managed API:

The System.Windows.Forms.SystemInformation managed class, which uses SystemParametersInfo internally, has many (but not all) static properties containing user information, system setup, and preferences.

Documentation