Home > Software design >  In vc6.0, using WinAPI to open the program to expand the monitor some problems, hope to get everyone
In vc6.0, using WinAPI to open the program to expand the monitor some problems, hope to get everyone

Time:04-13

Below is the main code, the problems encountered, and how they were resolved

***.h

std::list<DISPLAY_DEVICE> m_vDisplayDevice_list;
std::list<DEVMODE> m_vDevmode_list;
int m_nDisplayScreen;

***.cpp

std::list<DISPLAY_DEVICE> devices;
std::list<DEVMODE> modes;
int devId = 0;
BOOL ret = false;   // bool ret = false;
bool isPrimary = false;

//list all DisplayDevices (Monitors)
do
{
    DISPLAY_DEVICE displayDevice;
    ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
    displayDevice.cb = sizeof(displayDevice);   

    ret = EnumDisplayDevices(NULL, devId, &displayDevice, 0);
    if (ret != 0)   // reinterpret_cast
    {
        // 有‘DISPLAY_DEVICE_ATTACHED_TO_DESKTOP’标志的显示设备
        if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
        {
            devices.push_back(displayDevice);
            isPrimary = ((displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) == DISPLAY_DEVICE_PRIMARY_DEVICE);
        }
    }
    devId  ;
} while (ret);
m_vDisplayDevice_list = devices;
std::list<DISPLAY_DEVICE>::iterator it; 
for (it = m_vDisplayDevice_list.begin(); it != m_vDisplayDevice_list.end(); it  )
{
    DEVMODE deviceMode; 
    deviceMode.dmSize = sizeof(DEVMODE);
    deviceMode.dmFields = DM_PELSWIDTH |    // dmPelsWidth
        DM_PELSHEIGHT |                     //dmPelsHeight
        DM_BITSPERPEL | 
        DM_POSITION | 
        DM_DISPLAYFREQUENCY | 
        DM_DISPLAYFLAGS;    // | DM_DISPLAYORIENTATION;
    EnumDisplaySettings((const char*)(it->DeviceName), (int)ENUM_REGISTRY_SETTINGS, &deviceMode);
    modes.push_back(deviceMode);
}
m_vDevmode_list = modes;

I used this function to open the Windows desktop shortcut:

ShellExecute(NULL,
    NULL,
    _T("C:\\Users\\Administrator\\Desktop\\BasePointV - ***.lnk"),
    NULL,
    NULL,
    SW_SHOWNORMAL);

I have a problem!!!

--------Configuration: Display - Win32 Release--------
Linking...
***.obj : error LNK2001: unresolved external symbol __imp__EnumDisplayDevicesA@16
Debug/***.exe : fatal error LNK1120: 1 unresolved externals
***.exe - 1 error(s), 0 warning(s)


The project I built is MFC AppWinzard(exe);
Environment is:Windows10 VC 6.0
Online solutions include:
    Define WINVER 0x0500
    Add user32.DLL

There are many good solutions, but the linking problem is not solved yet! Although I am a novice, I would like to further collect some solutions

I hope to get your help to discuss and learn with you

CodePudding user response:

Your linkage error concerning _EnumDisplayDevices says it all.

My psychic powers suggests that since Visual Studio 6.0 (released in 1998) predates the availability of EnumDisplayDevices (Windows 2000), you are trying to pre-declare the API yourself. You probably predeclared EnumDisplayDevices manually yourself. Something like this:

BOOL EnumDisplayDevices(
    LPCSTR           lpDevice,
    DWORD            iDevNum,
    PDISPLAY_DEVICEA lpDisplayDevice,
    DWORD            dwFlags
);

There's two problems with this approach.

First, there's no API called EnumDisplayDevices. There is however, two APIs called EnumDisplayDevicesA and EnumDisplayDevicesW for both Unicode and ANSI builds. The Windows SDK will use a macro to map either one to the thing you can to invoke:

#ifdef UNICODE
#define EnumDisplayDevices  EnumDisplayDevicesW
#else
#define EnumDisplayDevices  EnumDisplayDevicesA
#endif // !UNICODE

Second, the actual declaration of EnumDisplayDevicesA and EnumDisplayDevicesW will are declared as stdcall calling type, like most Win32 APIs. Your declaration is likely missing this detail.

Hence, you want to declare this:

BOOL __stdcall EnumDisplayDevicesW(
    LPCWSTR lpDevice,
    DWORD iDevNum,
    PDISPLAY_DEVICEW lpDisplayDevice,
    DWORD dwFlags);

And this:

BOOL __stdcall EnumDisplayDevicesA(
    LPCSTR lpDevice,
    DWORD iDevNum,
    PDISPLAY_DEVICEA lpDisplayDevice,
    DWORD dwFlags);

If you manually declared DISPLAY_DEVICE and PDISPLAY_DEVICE yourself, you may also need to fixup your declaration as well. That's addressed in the sample code below.

Finally, even after you fix this, you still won't have a lib to link with since your version of user32.lib doesn't know anything about this API that came later.

You could find a newer version of the Windows SDK that still works with VC 6.0. But a simpler approach might to LoadLibrary the API directly at runtime. So putting it all together, here's a complete solution in which we'll dynamically load the EnumDisplayDevicesW and EnumDisplayDevicesA functions at runtime. Sample invocation as well:

#include <windows.h>

// BORROWED THIS FROM THE WINDOWS SDK - uncomment it if you need it
#if 0
typedef struct _DISPLAY_DEVICEA {
    DWORD  cb;
    CHAR   DeviceName[32];
    CHAR   DeviceString[128];
    DWORD  StateFlags;
    CHAR   DeviceID[128];
    CHAR   DeviceKey[128];
} DISPLAY_DEVICEA, *PDISPLAY_DEVICEA, *LPDISPLAY_DEVICEA;
typedef struct _DISPLAY_DEVICEW {
    DWORD  cb;
    WCHAR  DeviceName[32];
    WCHAR  DeviceString[128];
    DWORD  StateFlags;
    WCHAR  DeviceID[128];
    WCHAR  DeviceKey[128];
} DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW;
#ifdef UNICODE
typedef DISPLAY_DEVICEW DISPLAY_DEVICE;
typedef PDISPLAY_DEVICEW PDISPLAY_DEVICE;
typedef LPDISPLAY_DEVICEW LPDISPLAY_DEVICE;
#else
typedef DISPLAY_DEVICEA DISPLAY_DEVICE;
typedef PDISPLAY_DEVICEA PDISPLAY_DEVICE;
typedef LPDISPLAY_DEVICEA LPDISPLAY_DEVICE;
#endif // UNICODE
#endif // if 0

// Declare the function types for EnumDisplayDevices
typedef BOOL(__stdcall* FN_EDD_W)(LPCWSTR, DWORD, PDISPLAY_DEVICEW, DWORD);
typedef BOOL(__stdcall* FN_EDD_A)(LPCSTR, DWORD, PDISPLAY_DEVICEA, DWORD);


int main()
{
    FN_EDD_W fnEnumDisplayDevicesW;
    FN_EDD_A fnEnumDisplayDevicesA;

    // Dynamically load EnumDisplayDevices

    HMODULE hMod = LoadLibraryW(L"user32.dll");
    fnEnumDisplayDevicesW = (FN_EDD_W)GetProcAddress(hMod, "EnumDisplayDevicesW");
    fnEnumDisplayDevicesA = (FN_EDD_A)GetProcAddress(hMod, "EnumDisplayDevicesA");

    // now invoke the loaded API function
    DISPLAY_DEVICEW device = {};
    device.cb = sizeof(device);
    fnEnumDisplayDevicesW(NULL, 0, &device, 0); // equivalent to EnumDisplayDevicesW
}
  • Related