title: How can I get an HMONITOR handle from a display device name?
body: <p>I want to obtain a monitor handle (<code>HMONITOR</code>) that can be used with the Windows multi-monitor APIs for a <em>specific monitor</em> attached to the system <em>by index</em>. For example, say I have three monitors attached to my system and forming part of my desktop; I want to get a handle to monitor 3.</p>
  
  <p>I already know how to get the device name for a specific monitor by index by calling the <code>EnumDisplayDevices</code> function. For example:</p>
  
  <pre><code>HMONITOR MonitorFromIndex(int index /* (zero-indexed) */)
  {
      DISPLAY_DEVICE dd;
      dd.cb = sizeof(dd);
      if (EnumDisplayDevices(NULL, index, &amp;dd, 0) != FALSE)
      {
         // We found a match; make sure that it's part of the desktop.
         if ((dd.StateFlags &amp; DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
         {
            // Yup. Now we've got the name of the device:
            std::cout &lt;&lt; dd.DeviceName &lt;&lt; std::endl;
  
            // But how do I obtain an HMONITOR for this device?
            // ...
         }
      }
     return NULL;  // indicate failure
  }
  </code></pre>
  
  <p>In the code above, we've found the name of the desired device (<code>dd.DeviceName</code>). I can use this name to create a DC for that monitor by calling <code>CreateDC</code>:</p>
  
  <pre><code>HDC hDC = CreateDC(dd.DeviceName, dd.DeviceName, NULL, NULL);
  </code></pre>
  
  <p>And I can obtain information about that monitor by calling <code>EnumDisplaySettings</code>:</p>
  
  <pre><code>DEVMODE dm;
  dm.dmSize        = sizeof(dm);
  dm.dmDriverExtra = 0;
  if (EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &amp;dm) != FALSE)
  {
      std::cout &lt;&lt; "The monitor supports " &lt;&lt; dm.dmBitsPerPel &lt;&lt; " bits per pixel." &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>Which is all great, but I want a handle to that monitor. How can I get it?</p>
  
  <p>I tried to call <code>EnumDisplayMonitors</code>, passing a handle to the device context that I created using <code>CreateDC</code>, hoping to get a handle to the monitor passed to the callback function, but no such luck. The callback function was never called, and <code>EnumDisplayMonitors</code> returned <code>FALSE</code> (without setting an error code):</p>
  
  <pre><code>struct FoundMatch
  {
     BOOL     found;
     HMONITOR hMonitor;
  };
  
  BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
  {
     FoundMatch* pfm = reinterpret_cast&lt;FoundMatch*&gt;(dwData);
     pfm-&gt;found    = TRUE;
     pfm-&gt;hMonitor = hMonitor;
     return FALSE;  // stop enumerating
  }
  
  // elsewhere, after getting the device name and using it to create a DC
  FoundMatch fm;
  fm.found    = FALSE;
  fm.hMonitor = NULL;
  BOOL result = EnumDisplayMonitors(hDC, NULL, MonitorEnumProc, reinterpret_cast&lt;LPARAM&gt;(&amp;fm));
  </code></pre>