GetSystemMetrics

Retrieving Display Information and Mouse Settings from the Host Computer

May 16, 2006 - JanetTerra JanetTerra

You've made the perfect GUI display. The buttons, textboxes and other controls are all symmetrically lined up and your program appears so well polished. That is UNTIL you run the same program on another computer. The buttons are now only half visible along the lower edge, the textbox appears too close to the right edge, the scrollbars take up more pixels than you had thought. What happened here? If you are going to program for more than just personal use, you will need to accomodate for these visual changes evident in the different Windows operating systems and themes.

A classic example is the titlebar, or caption, height. Typically, the Windows 98 caption is 19 pixels high while the Windows XP caption is 26 pixels high. These 7 pixels are part of the WindowHeight, but are unavailable for the client space. A button placed at UL, 240, 240, on a Windows 96 display doesn't show up in the same spot as a button placed at UL, 240, 240, on a Windows XP display. Some users even have custom displays that further compound the inequality.

[[Image:GetSysMetPic.jpg "width=600" "height="347"]]

Even borders are not of standard width. The thicker border of a dialog window detracts more space away from the client working area than does a regular window border. Add a scrollbar to your graphics window and you no longer have a graphicbox of the desired width and height. Designing a 200 pixel by 200 pixel graphicbox with vertical and horizontal scrollbars means you'll have to add the size of the borders as well as the size of the scrollbars. Did you add a menu? Plan to lose even more pixels from your client window, but how many?

Fortunately, the #user32.dll call to GetSystemMetrics retrieves all this information and more. With GetSystemMetrics, you can find the caption height, available screen display height and width in pixels, the available client area display height and width in pixels, and a host of other dimensions. The GetSystemMetrics API can even tell you the width and height of the cursor being used and the width and height of menu checkmark bitmaps.

As well as dimensions, GetSystemMetrics can be very useful in obtaining mouse settings. This information includes
  • Is there a mouse present?
  • How many buttons does that mouse have?
  • Have the left and right buttons been swapped for a left - handed user?
  • How close in pixels does a double - click need to be?

There are at least 56 constants that can be sent to GetSystemMetrics for display, mouse and network settings. The following demo names and describes these 56 constants.

GetSystemMetrics
    nWindowsConstants = 56
 
    Dim WindowsConstant$(nWindowsConstants, 2)
    For i = 1 to nWindowsConstants
        Read Constant$, nIndex$, Description$
        WindowsConstant$(i, 0) = Constant$
        WindowsConstant$(i, 1) = Right$("0";nIndex$, 2)
        WindowsConstant$(i, 2) = Description$
    Next i
 
    Nomainwin
    WindowWidth = 800
    WindowHeight = 600
    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)
 
    Menu #main, "&Options", "E&xit", QuitByMenu
    Radiobutton #main.rb01, WindowsConstant$(1, 0), ChooseConstant, DeselectConstant, 40, 40, 150, 20
    Radiobutton #main.rb02, WindowsConstant$(2, 0), ChooseConstant, DeselectConstant, 40, 70, 150, 20
    Radiobutton #main.rb03, WindowsConstant$(3, 0), ChooseConstant, DeselectConstant, 40, 100, 150, 20
    Radiobutton #main.rb04, WindowsConstant$(4, 0), ChooseConstant, DeselectConstant, 40, 130, 150, 20
    Radiobutton #main.rb05, WindowsConstant$(5, 0), ChooseConstant, DeselectConstant, 40, 160, 150, 20
    Radiobutton #main.rb06, WindowsConstant$(6, 0), ChooseConstant, DeselectConstant, 40, 190, 150, 20
    Radiobutton #main.rb07, WindowsConstant$(7, 0), ChooseConstant, DeselectConstant, 40, 220, 150, 20
    Radiobutton #main.rb08, WindowsConstant$(8, 0), ChooseConstant, DeselectConstant, 40, 250, 150, 20
    Radiobutton #main.rb09, WindowsConstant$(9, 0), ChooseConstant, DeselectConstant, 40, 280, 150, 20
    Radiobutton #main.rb10, WindowsConstant$(10, 0), ChooseConstant, DeselectConstant, 40, 310, 150, 20
    Radiobutton #main.rb11, WindowsConstant$(11, 0), ChooseConstant, DeselectConstant, 40, 340, 150, 20
    Radiobutton #main.rb12, WindowsConstant$(12, 0), ChooseConstant, DeselectConstant, 40, 370, 150, 20
    Radiobutton #main.rb13, WindowsConstant$(13, 0), ChooseConstant, DeselectConstant, 40, 400, 150, 20
    Radiobutton #main.rb14, WindowsConstant$(14, 0), ChooseConstant, DeselectConstant, 40, 430, 150, 20
    Radiobutton #main.rb15, WindowsConstant$(15, 0), ChooseConstant, DeselectConstant, 40, 460, 150, 20
    Radiobutton #main.rb16, WindowsConstant$(16, 0), ChooseConstant, DeselectConstant, 40, 490, 150, 20
    Radiobutton #main.rb17, WindowsConstant$(17, 0), ChooseConstant, DeselectConstant, 240, 40, 150, 20
    Radiobutton #main.rb18, WindowsConstant$(18, 0), ChooseConstant, DeselectConstant, 240, 70, 150, 20
    Radiobutton #main.rb19, WindowsConstant$(19, 0), ChooseConstant, DeselectConstant, 240, 100, 150, 20
    Radiobutton #main.rb20, WindowsConstant$(20, 0), ChooseConstant, DeselectConstant, 240, 130, 150, 20
    Radiobutton #main.rb21, WindowsConstant$(21, 0), ChooseConstant, DeselectConstant, 240, 160, 150, 20
    Radiobutton #main.rb22, WindowsConstant$(22, 0), ChooseConstant, DeselectConstant, 240, 190, 150, 20
    Radiobutton #main.rb23, WindowsConstant$(23, 0), ChooseConstant, DeselectConstant, 240, 220, 150, 20
    Radiobutton #main.rb24, WindowsConstant$(24, 0), ChooseConstant, DeselectConstant, 240, 250, 150, 20
    Radiobutton #main.rb25, WindowsConstant$(25, 0), ChooseConstant, DeselectConstant, 240, 280, 150, 20
    Radiobutton #main.rb26, WindowsConstant$(26, 0), ChooseConstant, DeselectConstant, 240, 310, 150, 20
    Radiobutton #main.rb27, WindowsConstant$(27, 0), ChooseConstant, DeselectConstant, 240, 340, 150, 20
    Radiobutton #main.rb28, WindowsConstant$(28, 0), ChooseConstant, DeselectConstant, 240, 370, 150, 20
    Radiobutton #main.rb29, WindowsConstant$(29, 0), ChooseConstant, DeselectConstant, 240, 400, 150, 20
    Radiobutton #main.rb30, WindowsConstant$(30, 0), ChooseConstant, DeselectConstant, 240, 430, 150, 20
    Radiobutton #main.rb31, WindowsConstant$(31, 0), ChooseConstant, DeselectConstant, 240, 460, 150, 20
    Radiobutton #main.rb32, WindowsConstant$(32, 0), ChooseConstant, DeselectConstant, 240, 490, 150, 20
    Radiobutton #main.rb33, WindowsConstant$(33, 0), ChooseConstant, DeselectConstant, 440, 40, 150, 20
    Radiobutton #main.rb34, WindowsConstant$(34, 0), ChooseConstant, DeselectConstant, 440, 70, 150, 20
    Radiobutton #main.rb35, WindowsConstant$(35, 0), ChooseConstant, DeselectConstant, 440, 100, 150, 20
    Radiobutton #main.rb36, WindowsConstant$(36, 0), ChooseConstant, DeselectConstant, 440, 130, 150, 20
    Radiobutton #main.rb37, WindowsConstant$(37, 0), ChooseConstant, DeselectConstant, 440, 160, 150, 20
    Radiobutton #main.rb38, WindowsConstant$(38, 0), ChooseConstant, DeselectConstant, 440, 190, 150, 20
    Radiobutton #main.rb39, WindowsConstant$(39, 0), ChooseConstant, DeselectConstant, 440, 220, 150, 20
    Radiobutton #main.rb40, WindowsConstant$(40, 0), ChooseConstant, DeselectConstant, 440, 250, 150, 20
    Radiobutton #main.rb41, WindowsConstant$(41, 0), ChooseConstant, DeselectConstant, 440, 280, 150, 20
    Radiobutton #main.rb42, WindowsConstant$(42, 0), ChooseConstant, DeselectConstant, 440, 310, 150, 20
    Radiobutton #main.rb43, WindowsConstant$(43, 0), ChooseConstant, DeselectConstant, 440, 340, 150, 20
    Radiobutton #main.rb44, WindowsConstant$(44, 0), ChooseConstant, DeselectConstant, 440, 370, 150, 20
    Radiobutton #main.rb45, WindowsConstant$(45, 0), ChooseConstant, DeselectConstant, 640, 40, 150, 20
    Radiobutton #main.rb46, WindowsConstant$(46, 0), ChooseConstant, DeselectConstant, 640, 70, 150, 20
    Radiobutton #main.rb47, WindowsConstant$(47, 0), ChooseConstant, DeselectConstant, 640, 100, 150, 20
    Radiobutton #main.rb48, WindowsConstant$(48, 0), ChooseConstant, DeselectConstant, 640, 130, 150, 20
    Radiobutton #main.rb49, WindowsConstant$(49, 0), ChooseConstant, DeselectConstant, 640, 160, 150, 20
    Radiobutton #main.rb50, WindowsConstant$(50, 0), ChooseConstant, DeselectConstant, 640, 190, 150, 20
    Radiobutton #main.rb51, WindowsConstant$(51, 0), ChooseConstant, DeselectConstant, 640, 220, 150, 20
    Radiobutton #main.rb52, WindowsConstant$(52, 0), ChooseConstant, DeselectConstant, 640, 250, 150, 20
    Radiobutton #main.rb53, WindowsConstant$(53, 0), ChooseConstant, DeselectConstant, 640, 280, 150, 20
    Radiobutton #main.rb54, WindowsConstant$(54, 0), ChooseConstant, DeselectConstant, 640, 310, 150, 20
    Radiobutton #main.rb55, WindowsConstant$(55, 0), ChooseConstant, DeselectConstant, 640, 340, 150, 20
    Radiobutton #main.rb56, WindowsConstant$(56, 0), ChooseConstant, DeselectConstant, 640, 370, 150, 20
    Stylebits #main.desc, _ES_READONLY or _WS_VSCROLL OR _ES_MULTILINE, _ES_AUTOHSCROLL, 0, 0
    Textbox #main.desc, 450, 410, 300, 100
    Open "#user32: GetSystemsMetric" for Window as #main
    #main "Trapclose QuitByTrap"
    #main "Font Times_New_Roman 8 Bold"
    #main.desc "!Font Times_New_Roman 12 Bold"
    Wait
 
Sub QuitByTrap handle$
    Close #main
    End
End Sub
 
Sub QuitByMenu
    Call QuitByTrap "#main"
End Sub
 
Sub ChooseConstant handle$
    RBExt = Val(Right$(handle$, 2))
    WindowsConstant = Val(WindowsConstant$(RBExt, 1))
    ReturnedValue = GetSystemMetrics(WindowsConstant)
    text$ = WindowsConstant$(RBExt, 0);" = ";Str$(WindowsConstant);Chr$(13);Chr$(10) + _
    WindowsConstant$(RBExt, 2);Chr$(13);Chr$(10);"Returned Value = ";ReturnedValue
    #main.desc text$
End Sub
 
Function GetSystemMetrics(nIndex)
    CallDLL #user32, "GetSystemMetrics", _
        nIndex as Long, _
        GetSystemMetrics as Long
End Function
 
 
 
Data "_SM_CXSCREEN", "0"
Data"Width of Screen"
Data "_SM_CYSCREEN", "1"
Data "Height of screen"
Data "_SM_CXVSCROLL", "2"
Data "Width of arrow bitmap on vertical scroll bar"
Data "_SM_CYHSCROLL", "3"
Data "Height of arrow bitmap on horizontal scroll bar"
Data "_SM_CYCAPTION", "4"
Data "Height of caption or title"
Data "_SM_CXBORDER", "5"
Data "Width of window frame that cannot be sized"
Data "_SM_CYBORDER", "6"
Data "Height of window frame that cannot be sized"
Data "_SM_CXDLGFRAME", "7"
Data "Width of dialog frame window"
Data "_SM_CYDLGFRAME", "8"
Data "Height of dialog frame window"
Data "_SM_CYVTHUMB", "9"
Data "Width of scroll box (thumb) on vertical scroll bar"
Data "_SM_CXHTHUMB", "10"
Data "Width of scroll box (thumb) on horizontal scroll bar"
Data "_SM_CXICON", "11"
Data "Width of icon"
Data "_SM_CYICON", "12"
Data "Height of icon"
Data "_SM_CXCURSOR", "13"
Data "Width of cursor"
Data "_SM_CYCURSOR", "14"
Data "Height of cursor"
Data "_SM_CYMENU", "15"
Data "Height of menu"
Data "_SM_CXFULLSCREEN", "16"
Data "Width of window client area"
Data "_SM_CYFULLSCREEN", "17"
Data "Height of window client area"
Data "_SM_CYKANJIWINDOW", "18"
Data "Height of Kanji window"
Data "_SM_MOUSEPRESENT", "19"
Data "Non-zero if mouse hardware is installed"
Data "_SM_CYVSCROLL", "20"
Data "Height of arrow bitmap on vertical scroll bar"
Data "_SM_CXHSCROLL", "21"
Data "Width of arrow bitmap on horizontal scroll bar"
Data "_SM_DEBUG", "22"
Data "Returns non-zero if the Windows  version is a debugging version"
Data "_SM_SWAPBUTTON", "23"
Data "Non-zero if the left and right mouse buttons are swapped"
Data "_SM_CXMIN", "28"
Data "Minimum width of window"
Data "_SM_CYMIN", "29"
Data "Minimum height of window"
Data "_SM_CXSIZE", "30"
Data "Width of bitmaps in title bar"
Data "_SM_CYSIZE", "31"
Data "Height of bitmaps in title bar"
Data "_SM_CXFRAME", "32"
Data "Width of window frame"
Data "_SM_CYFRAME", "33"
Data "Height of window frame"
Data "_SM_CXMINTRACK", "34"
Data "Minimum tracking width of window"
Data "_SM_CYMINTRACK", "35"
Data "Minimum tracking height of window"
Data "_SM_CXDOUBLECLICK", "36"
Data "Second click must occur within this width of rectangular location"
Data "_SM_CYDOUBLECLICK", "37"
Data "Second click must occur within this height of rectangular location"
Data "_SM_CXICONSPACING", "38"
Data "Width of rectangles the system uses to position tiled icons"
Data "_SM_CYICONSPACING", "39"
Data "Height of rectangles the system uses to position tiled icons"
Data "_SM_MENUDROPALIGNMENT", "40"
Data "Alignment of pop-up menus. Zero=left side of menubar item; non-zero=right side of menu bar item"
Data "_SM_PENWINDOWS", "41"
Data "Handle of Pen Windows dynamic link library if Pen Windows is  installed"
Data "_SM_DBCSENABLED", "42"
Data "Returns a non-zero if the current Windows version uses double-byte characters, otherwise returns zero"
Data "_SM_CMOUSEBUTTONS", "43"
Data "Number of mouse buttons"
Data "_SM_SECURE", "44"
Data "True if security is present on Windows 95 system"
Data "_SM_CYSMCAPTION", "51"
Data "Height of Windows 95 small caption"
Data "_SM_CXMENUSIZE", "54"
Data "Width of button on menu bar"
Data "_SM_CYMENUSIZE", "55"
Data "Height of button on menu bar"
Data "_SM_CXMINIMIZED", "57"
Data "Width of rectangle into which minimised windows must fit"
Data "_SM_CYMINIMIZED", "58"
Data "Height of rectangle into which minimised windows must fit"
Data "_SM_CXMAXTRACK", "59"
Data "Maximum width when resizing Windows 95 windows"
Data "_SM_CYMAXTRACK", "60"
Data "Maximum height when resizing Windows 95 windows"
Data "_SM_CXMAXIMIZED", "61"
Data "Default width of Windows 95 maximised window"
Data "_SM_CYMAXIMIZED", "62"
Data "Default height of Windows 95 maximised window"
Data "_SM_NETWORK", "63"
Data "Bit o is set if a network is present."
Data "_SM_CLEANBOOT", "67"
Data "Windows 95 boot mode. 0 = normal, 1 = safe, 2 = safe with network"
Data "_SM_CXMENUCHECK", "71"
Data "Width of menu checkmark bitmap"
Data "_SM_CYMENUCHECK", "72"
Data "Height of menu checkmark bitmap"
Data "_SM_SLOWMACHINE", "73"
Data "True if machine is too slow to run Windows 95."
Data "_SM_MIDEASTENABLED", "74"
Data "Hebrew and Arabic enabled for Windows 95."
The sources for these constants are http://support.microsoft.com/?kbid=210603 and http://www.allapi.net/tips/tip017.shtml