SystemParametersInfo (user32)
Last changed: -212.117.77.91

.
Summary

C# Signature:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, IntPtr pvParam, SPIF fWinIni);

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, String pvParam, SPIF fWinIni);

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

User-Defined Types:

SPI, SPIF, ANIMATIONINFO

VB.Net Signature:

    Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Integer, _
      ByVal uParam As Integer, ByVal lpvParam As Integer, _
      ByVal fuWinIni As Integer) As Integer

'=========================================================
Imports System.Runtime.InteropServices

<DllImport("user32", CharSet:=CharSet.Auto)> _
Public Shared Function SystemParametersInfo( _
            ByVal intAction As Integer, _
            ByVal intParam As Integer, _
            ByVal strParam As String, _
            ByVal intWinIniFlag As Integer) As Integer
' returns non-zero value if function succeeds
End Function

Notes:

For VB the strParam is an _in or _out of String type.  Must be ByRef if used to query/retrieve. Otherwise use ByVal.

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);

Changing the wallpaper. Note, only works for BMP. Must convert to BMP format if using JPEG, GIF, etc. (EDIT : In Windows Vista, at least, this works with other image types, including JPEG and GIF)

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String         pvParam, UInt32 fWinIni);
    private static UInt32 SPI_SETDESKWALLPAPER = 20;
    private static UInt32 SPIF_UPDATEINIFILE = 0x1;
    private String imageFileName = "c:\\sample.bmp";

    public void SetImage( string filename )
    {
        SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, filename, SPIF_UPDATEINIFILE);
    }

VB NET Changing the Wallpaper. Note for above example applies if Window XP or below.

' before Public Class class_name
Imports System.Runtime.InteropServices

'after Public Class class_name
Const SPI_SetWallpaper As Integer = &H14
'Win.ini flag values (intWinIniFlag)
Const SPIF_UpdateIni As Integer = 1
Const SPIF_SendIniChange As Integer = 2
Const SPIF_UpdateAndSend As Integer = SPIF_UpdateIni Or SPIF_SendIniChange '3

' SetLastError:=True is required for error checking
<DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function SystemParametersInfo( _
            ByVal intAction As Integer, _
            ByVal intParam As Integer, _
            ByVal strParam As String, _
            ByVal intWinIniFlag As Integer) As Integer
' returns non-zero value if function succeeds
End Function

Dim strFile as String = "WhateverFileName.bmp"
Dim intReturn As Integer = Nothing
Dim intError As Integer = Nothing
intReturn = SystemParametersInfo(SPI.SetWallpaper, 0, strFile, SPIF.UpdateAndSend)
intError = Marshal.GetLastWin32Error()
if ret <> 0 Then
' intError contains the error number
End If

Return type of some native methods like SystemParametersInfo is bool. They should be marked by System.Runtime.InteropServices.MarshalAsAttribute.

    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SystemParametersInfo(SystemParametersInfoActions uAction, uint uParam, ref uint lpvParam, uint fuWinIni);

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.

Also, System.Drawing.SystemFonts contains all the font settings which can be returned by SystemParametersInfo.

Documentation