UltraMon™ multi-monitor components

Low-level multi-monitor programming can be difficult: API differences between Win9x and NT-based platforms, undocumented features. And the only available API is intended for C programmers, making it even more difficult for Visual Basic developers, and unusable for scripting.

That's where the UltraMon™ multi-monitor components come in: COM components compatible with most programming languages, providing a single multi-monitor API on all platforms.

In the following paragraphs I'll show you how you can use UltraMon components from VBScript, Visual Basic and C++. For more samples and complete documentation, download the UltraMon SDK. The source code for the samples below is also included in the SDK.

Requirements

UltraMon

VBScript

I love scripting, so let's begin with that. The following code displays information about each installed monitor.

Const REFRATE_DEFAULT = 0
Const REFRATE_OPTIMAL = -1

Set sys = CreateObject("UltraMon.System")

For Each mon In sys.Monitors
  msg = msg & "Monitor " & mon.ID & ": " & mon.Name & vbNewline
  msg = msg & "Video card: " & mon.AdapterName & vbNewline
  If mon.Enabled = True Then
    'refresh rate can be in Hz or one of the values from the REFRATE enumeration
    Select Case mon.RefreshRate
      Case REFRATE_DEFAULT
        refRate = "default refresh rate"
      Case REFRATE_OPTIMAL
        refRate = "optimal refresh rate"
      Case Else
        refRate = mon.RefreshRate & " Hz"
    End Select

    msg = msg & "Display mode: " & mon.Width & "x" & mon.Height & " " & mon.Colordepth & "-bit " & refRate & vbNewline
    msg = msg & "Position: " & mon.Left & "," & mon.Top & vbNewline & vbNewline
  Else
    msg = msg & "(disabled)" & vbNewline & vbNewline
  End If
Next

MsgBox msg, vbOKOnly, "System information"

Visual Basic

You could use pretty much the same code as for VBScript, but you can take advantage of early binding for improved performance:

Dim sys As New UltraMonSystem

instead of

Dim sys
Set sys = CreateObject("UltraMon.System")

And of course you don't need to define the constants manually, simply referencing the UltraMon 2.0 type library is enough.

C++

Here is the same sample in C++. ComString is a BSTR wrapper, which makes handling the strings used by UltraMon a lot simpler. ComString is included in the SDK.

// initialize COM
CoInitializeEx(0, COINIT_APARTMENTTHREADED);

// create the UltraMon System object
IUltraMonSystem* pSys = 0;
CoCreateInstance(CLSID_UltraMonSystem, 0, CLSCTX_ALL, IID_IUltraMonSystem,
  reinterpret_cast<void**>(&pSys));

// get a pointer to the monitor collection, and determine the number of installed monitors
IUltraMonMonitors* pMonitors = 0;
pSys->get_Monitors(&pMonitors);

long numMonitors = 0;
pMonitors->get_Count(&numMonitors);

// allocate a string buffer to hold the system information
// we assume that there will never be more than 1000 characters per monitor
TCHAR* buf = new TCHAR[numMonitors * 1000];
*buf = _T('\0');

// enumerate all monitors, and get information about each one
VARIANT vt;
vt.vt = VT_I4;

for (int i = 0; i < numMonitors; ++i)
{
  // get a pointer to the monitor
  IUltraMonMonitor* pMonitor = 0;
  vt.lVal = i;
  pMonitors->Item(vt, &pMonitor);

  // format the information about this monitor
  TCHAR monInfo[1000] = _T("");

  // monitor name
  ComString str;
  pMonitor->get_Name(&str);
  wsprintf(monInfo, _T("Monitor %d: %s\r\n"), i + 1, static_cast<TCHAR*>(str));
  lstrcat(buf, monInfo);

  // video card name
  pMonitor->get_AdapterName(&str);
  wsprintf(monInfo, _T("Video card: %s\r\n"), static_cast<TCHAR*>(str));
  lstrcat(buf, monInfo);

  // check if the monitor is enabled
  VARIANT_BOOL enabled;
  pMonitor->get_Enabled(&enabled);
  if (enabled == VARIANT_TRUE)
  {
    // the monitor is enabled

    // display mode
    long width, height;
    short colordepth;
    pMonitor->get_Width(&width);
    pMonitor->get_Height(&height);
    pMonitor->get_Colordepth(&colordepth);

    // refresh rate can be in Hz, or one of the values from the REFRATE enumeration
    short refreshRate;
    TCHAR refreshRateStr[50] = _T("");
    pMonitor->get_RefreshRate(&refreshRate);
    switch (refreshRate)
    {
    case REFRATE_DEFAULT:
      lstrcpy(refreshRateStr, _T("default refresh rate"));
      break;

    case REFRATE_OPTIMAL:
      lstrcpy(refreshRateStr, _T("optimal refresh rate"));
      break;

    default:
      wsprintf(refreshRateStr, _T("%d Hz"), refreshRate);
    }

    wsprintf(monInfo, _T("Display mode: %dx%d %d-bit %s\r\n"), width, height, colordepth,
      refreshRateStr);
    lstrcat(buf, monInfo);

    // position
    long left, top;
    pMonitor->get_Left(&left);
    pMonitor->get_Top(&top);
    wsprintf(monInfo, _T("Position: %d,%d\r\n\r\n"), left, top);
    lstrcat(buf, monInfo);
  }
  else
  {
    // the monitor is disabled

    lstrcat(buf, _T("(disabled)\r\n\r\n"));
  }

  pMonitor->Release();
}

// display message box
MessageBox(0, buf, _T("System information"), MB_OK);

// release resources
delete [] buf;
pMonitors->Release();
pSys->Release();

// uninitialize COM
CoUninitialize();

Other features

Besides getting information about a system's multi-monitor configuration, you can also

  • change monitor settings like resolution, colordepth, refresh rate and position
  • enable and disable monitors
  • change the primary monitor (Windows 2000/XP only)
  • save/restore position of windows, desktop icons and Active Desktop items
  • get and set various window properties
  • move windows to a different monitor
  • maximize windows to the desktop

More information

For complete documentation and more samples, download the software development kit. If you have any questions about programming with UltraMon, post them to the UltraMon SDK forum.