Detect/identify the port (HDMI, other) the monitor is connected to in Windows 7/8/10 Win32 C++

坚强是说给别人听的谎言 提交于 2019-12-09 01:20:29

问题


I am able to detect all the monitors that are connected to my system. I am able to get a lot of relevant information about them using the following Windows API calls:

EnumDisplayMonitors

GetMonitorInfo

EnumDisplayDevices

The system I am developing on is an AIO (all-in-one) that comes with 2 monitors. It has an external HDMI output that I can connect and external monitor. Then, through a port replicator I am able to connect the 4th monitor. All of the monitors are extending my desktop and all of them are working fine.

My task is to detect the monitor that is connected through the HDMI port. The monitor information that I am able to extract using the above mentioned API do not give any specific information through which I will be able to detect the port type (e.g. HDMI, or USB).

Does anyone know what API to use? Thanks!


回答1:


You can use the EnumDisplayDevices method to get the DeviceID of the monitor and then the WmiMonitorConnectionParams WMI class (available since Windows Vista) and the VideoOutputTechnology property which returns a D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY enumeration.

Try the next sample code

#include "stdafx.h"
#include <atlstr.h>
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")            


typedef enum _D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY {
    D3DKMDT_VOT_UNINITIALIZED = -2,
    D3DKMDT_VOT_OTHER = -1,
    D3DKMDT_VOT_HD15 = 0,
    D3DKMDT_VOT_SVIDEO = 1,
    D3DKMDT_VOT_COMPOSITE_VIDEO = 2,
    D3DKMDT_VOT_COMPONENT_VIDEO = 3,
    D3DKMDT_VOT_DVI = 4,
    D3DKMDT_VOT_HDMI = 5,
    D3DKMDT_VOT_LVDS = 6,
    D3DKMDT_VOT_D_JPN = 8,
    D3DKMDT_VOT_SDI = 9,
    D3DKMDT_VOT_DISPLAYPORT_EXTERNAL = 10,
    D3DKMDT_VOT_DISPLAYPORT_EMBEDDED = 11,
    D3DKMDT_VOT_UDI_EXTERNAL = 12,
    D3DKMDT_VOT_UDI_EMBEDDED = 13,
    D3DKMDT_VOT_SDTVDONGLE = 14,
#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM1_3_M1)
    D3DKMDT_VOT_MIRACAST = 15,
#endif 
    D3DKMDT_VOT_INTERNAL = 0x80000000,
    D3DKMDT_VOT_SVIDEO_4PIN = D3DKMDT_VOT_SVIDEO,
    D3DKMDT_VOT_SVIDEO_7PIN = D3DKMDT_VOT_SVIDEO,
    D3DKMDT_VOT_RF = D3DKMDT_VOT_COMPOSITE_VIDEO,
    D3DKMDT_VOT_RCA_3COMPONENT = D3DKMDT_VOT_COMPONENT_VIDEO,
    D3DKMDT_VOT_BNC = D3DKMDT_VOT_COMPONENT_VIDEO
} D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY;

_D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY GetConnectorInfo(LPCWSTR ShortDeviceID)
{
    _D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY result = D3DKMDT_VOT_OTHER;

    BSTR strNetworkResource;
    strNetworkResource = L"\\\\.\\root\\WMI";

    HRESULT hres;
    hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        cout << "press enter to exit" << endl;
        cin.get();
        std::exit(1);
    }


    hres = CoInitializeSecurity(
        NULL,
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities
        NULL                         // Reserved
        );

    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();
        std::exit(1);
    }

    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();
        std::exit(1);
    }


    IWbemServices *pSvc = NULL;

    hres = pLoc->ConnectServer(
        _bstr_t(strNetworkResource),      // Object path of WMI namespace
        NULL,                    // User name. NULL = current user
        NULL,                    // User password. NULL = current
        0,                       // Locale. NULL indicates current
        NULL,                    // Security flags.
        0,                       // Authority (e.g. Kerberos)
        0,                       // Context object
        &pSvc                    // pointer to IWbemServices proxy
        );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();
        std::exit(1);
    }

    hres = CoSetProxyBlanket(
        pSvc,                        // Indicates the proxy to set
        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
        NULL,                        // Server principal name
        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL,                        // client identity
        EOAC_NONE                    // proxy capabilities
        );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();
        std::exit(1);
    }


    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(L"WQL", L"SELECT InstanceName, VideoOutputTechnology FROM WmiMonitorConnectionParams",
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);

    if (FAILED(hres))
    {
        cout << "ExecQuery failed" << " Error code = 0x" << hex << hres << endl;
        cout << _com_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();
        std::exit(1);
    }


    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;
    BOOL bFound = false;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

        if (0 == uReturn || FAILED(hr))
            break;

        VARIANT vtProp;
        CString DeviceID;
        hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0);// String
        if (!FAILED(hr))
        {
            if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
            { }
            else
            {
                DeviceID.Format(L"%s", vtProp.bstrVal);
                DeviceID = DeviceID.Mid(8, DeviceID.Find(L"\\", 9) - 8);
                bFound = DeviceID.Compare(ShortDeviceID) == 0;
            }
        }
        VariantClear(&vtProp);

        if (bFound)
        {
            hr = pclsObj->Get(L"VideoOutputTechnology", 0, &vtProp, 0, 0);// Uint32
            if (!FAILED(hr))
            {
                if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
                    result = D3DKMDT_VOT_OTHER;
                else
                {
                    result = (_D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY)vtProp.uintVal;
                }
            }
        }
        VariantClear(&vtProp);


        pclsObj->Release();
        pclsObj = NULL;

        if (bFound)
            break;
    }


    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    if (pclsObj != NULL)
        pclsObj->Release();

    CoUninitialize();

    return result;
}



void GetDisplayInfo()
{

    DISPLAY_DEVICE lpDisplayDevice;
    lpDisplayDevice.cb = sizeof(lpDisplayDevice);
    DWORD iDevNum = 0;

    CString DeviceID;
    while (EnumDisplayDevices(0, iDevNum, &lpDisplayDevice, 0))
    {
        DISPLAY_DEVICE lpDisplayDevice2;
        ZeroMemory(&lpDisplayDevice2, sizeof(lpDisplayDevice2));
        lpDisplayDevice2.cb = sizeof(lpDisplayDevice2);
        DWORD devMon = 0;

        while (EnumDisplayDevices(lpDisplayDevice.DeviceName, devMon, &lpDisplayDevice2, 0))
        {
            if (lpDisplayDevice2.StateFlags & DISPLAY_DEVICE_ACTIVE && !(lpDisplayDevice2.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
            {
                DeviceID.Format(L"%s", lpDisplayDevice2.DeviceID);
                wcout << DeviceID.GetString() << endl;
                DeviceID = DeviceID.Mid(8, DeviceID.Find(L"\\", 9) - 8);
                _D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY VideoOutputTechnology = GetConnectorInfo(DeviceID.GetString());

                switch (VideoOutputTechnology) 
                {
                case D3DKMDT_VOT_HDMI:
                    wcout << " VideoOutputTechnology : HDMI" << endl;
                    break;
                case D3DKMDT_VOT_INTERNAL:
                    wcout << " VideoOutputTechnology : Internal Monitor" << endl;
                    break;
                default:
                    wcout << " VideoOutputTechnology : " << VideoOutputTechnology << endl;
                    break;
                }

            }
            devMon++;

            ZeroMemory(&lpDisplayDevice2, sizeof(lpDisplayDevice2));
            lpDisplayDevice2.cb = sizeof(lpDisplayDevice2);
        }

        ZeroMemory(&lpDisplayDevice, sizeof(lpDisplayDevice));
        lpDisplayDevice.cb = sizeof(lpDisplayDevice);
        iDevNum++;
    }
}

int main(int argc, char* argv[])
{
    GetDisplayInfo();
    cout << "press enter to exit" << endl;
    cin.get();
    return 0;  
}

This will return something like

MONITOR\CMN15BB\{4d36e96e-e325-11ce-bfc1-08002be10318}\0001
   VideoOutputTechnology : Internal Monitor 
MONITOR\SNY7702\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000  
   VideoOutputTechnology : HDMI


来源:https://stackoverflow.com/questions/31712915/detect-identify-the-port-hdmi-other-the-monitor-is-connected-to-in-windows-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!