EnumDisplayMonitors Troubles – NvCpl solutions.

Recently I had EnumDisplayMonitors presenting some strange behaviour, exposing 2 monitors when in fact only one was connected. The nVidia Control panel API eventually came to the rescue – it exposes the entire functionality available via the nVidia control panel, and implemented in NvCpl.dll in the Windows\system32 folder. Specifically NvCplRefreshConnectedDevices(), quote from the manual, ‘refreshes the connection state cache for all display outputs on the selected GPU’. Never heard of the ‘connection state cache’ – indeed, by the documentation another API (NvCplGetActiveDevicesString), retrieves the ‘connected device state that was cached by the driver during such system events as bootup, logon, or opening of the display properties control panel’. Bottom line, the following code solved the problem:

typedef BOOL (APIENTRY *NvRefreshProc)( IN DWORD );

VOID RefreshDisplayCache()
   HANDLE hNvCpl = LoadLibrary(_T("NvCpl"));

   // The graphics driver caches monitors setup, and sometimes gets out of sync.
   // Here we force a refresh.
   if (hNvCpl)
      NvRefreshProc ProcRefresh = (NvRefreshProc)
            GetProcAddress(hNvCpl, "NvCplRefreshConnectedDevices");

      if (ProcRefresh)
            (ProcRefresh) (1);  // input flag - NVREFRESH_NONINTRUSIVE

As an added bonus, I’m now able to programmatically set ‘fixed aspect-ratio scaling’, which I couldn’t until now.

typedef DWORD (APIENTRY *dtcfgexPROC)( LPSTR );


// change display to fixed aspect-ratio scaling, so as not to distort the
	// picture on wide screens.
	if (hNvCpl)
		dtcfgexPROC ProcAdd = (dtcfgexPROC) GetProcAddress(m_hNvCpl, "dtcfgex");

		if (ProcAdd)
			(ProcAdd) ("setscaling 1 5"); // set scaling on display #1 to mode 5 (fixed aspect ratio)

(check out dtcfgex in the manual for details.) The API contains lots of other low level goodies. If you make extensive use of it, you might prefer to statically link against NvCpl.dll and include the header NvCpl.h (contained in this nVidia sample download). I have no idea how to achieve both tasks on ATI cards (and whether similar cache or scaling mode even exists there) but we ship only nVidia’s – so no worries there, for now.

This entry was posted in Win32. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s