Проверка на подключённые дивайсы

Tema05

Известный
Автор темы
1,429
396
Версия MoonLoader
.026-beta
Как можно проверить, что к компу подключена мышка, клава или то что включён монитор?

UPD1: Это как-то делается через ffi интерфейс и windows api. Решил начать с монитора и того что он вообще подключен.

Взял отсюда https://stackoverflow.com/a/14377835 код
C++:
BOOL IsDisplayConnected(int displayIndex = 0)
{
    DISPLAY_DEVICE device;
    device.cb = sizeof(DISPLAY_DEVICE);
    return EnumDisplayDevices(NULL, displayIndex, &device, 0);
}
и переделал на lua
Lua:
local ffi = require 'ffi'
ffi.cdef [[
    typedef struct {
        uint32_t cb;
        char DeviceName[32];
        char DeviceString[128];
        uint32_t StateFlags;
        char DeviceID[128];
        char DeviceKey[128];
    } DISPLAY_DEVICE;
    int EnumDisplayDevicesA(const char* lpDevice, int iDevNum, DISPLAY_DEVICE* lpDisplayDevice , unsigned long dwFlags);
]]
local user32 = ffi.load("user32")
local device = ffi.new("DISPLAY_DEVICE")
device.cb = ffi.sizeof("DISPLAY_DEVICE")
if user32.EnumDisplayDevicesA(nil, 0 --[[display index]], device, 0) ~= 0 and bit.band(device.StateFlags, 1 --[[DISPLAY_DEVICE_ACTIVE]]) ~= 0 then
    print('+', ffi.string(device.DeviceName), ffi.string(device.DeviceString), ffi.string(device.DeviceID), ffi.string(device.DeviceKey))
else
    print('-')
end
Даже если я вытыкал DP кабель из ПК он всё равно определял наличие монитора, а все параметры не изменялись.
Код:
DeviceName - \\.\DISPLAY1
DeviceString - NVIDIA GeForce RTX 3060
StateFlags - 5
DeviceID - PCI\VEN_10DE&DEV_2487&SUBSYS_39771462&REV_A1
DeviceKey - \Registry\Machine\System\CurrentControlSet\Control\Video\{0FEAF640-675D-11ED-B368-B42E99F8170D}\0000
меня смущает почему тут указана видеокарта. Я же мониторы получаю. Если втыкать провод в другие слоты видюхи параметры тоже не меняются.

Я решил попробовать зайти по-другому и получать количество подключённых мониторов. Но значение также всегда было 1.
Lua:
local ffi = require 'ffi'

ffi.cdef [[
    int GetSystemMetrics(int nIndex);
]]

local user32 = ffi.load("user32")

print(user32.GetSystemMetrics(80--[[SM_CMONITORS]]))

UPD2: ещё пытался определить что-то по хендлу монитора через хвид рабочего стола. Опять же значения с воткнутым провод и нет идентичны. Разрешение получается. У меня 2к. 1390 это за вычетом высоты панели задач. Следовательно я точно обращаюсь куда надо
Lua:
ffi = require 'ffi'

ffi.cdef [[
    typedef void* HMONITOR;
    typedef unsigned long DWORD;

    typedef struct {
        long left;
        long top;
        long right;
        long bottom;
    } RECT;
    typedef struct {
        DWORD cbSize;
        RECT  rcMonitor;
        RECT  rcWork;
        DWORD dwFlags;
    } MONITORINFO;

    void* GetDesktopWindow();
    HMONITOR MonitorFromWindow(void* hwnd, unsigned long dwFlags);
    int GetMonitorInfoA(HMONITOR hMonitor, MONITORINFO* lpmi);
]]

local user32 = ffi.load("user32")

local desktopWindow = user32.GetDesktopWindow()
local monitor = user32.MonitorFromWindow(desktopWindow, 2 --[[MONITOR_DEFAULTTONEAREST]])

if monitor ~= nil then
    local monitorInfo = ffi.new("MONITORINFO")
    monitorInfo.cbSize = ffi.sizeof("MONITORINFO")
    if user32.GetMonitorInfoA(monitor, monitorInfo) ~= 0 and bit.band(monitorInfo.dwFlags, 1 --[[MONITORINFOF_PRIMARY]]) ~= 0 then
        print(monitorInfo.cbSize, monitorInfo.dwFlags)
        print(monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, monitorInfo.rcMonitor.right, monitorInfo.rcMonitor.bottom)
        print(monitorInfo.rcWork.left, monitorInfo.rcWork.top, monitorInfo.rcWork.right, monitorInfo.rcWork.bottom)
    else
        print("-")
    end
else
    print("-")
end
Код:
[19:13:22.174496] (script)    main.lua: 40   1
[19:13:22.174496] (script)    main.lua: 0   0   2560   1440
[19:13:22.174496] (script)    main.lua: 0   0   2560   1390

UPD3: Я понял ошибку. Там выходит дивайс дивайса. Нужно функцией EnumDisplayDevicesA с 1 параметром nil получить адапторы дисплея и потом название адаптера засунуть в неё же уже получив мониторы этого адаптера. Ниже код определения подключённого хотя бы 1 монитора. Теперь нужно определить включён ли он. При выключении монитора никакие значения не меняются. StateFlags всегда 3
Lua:
local ffi = require 'ffi'

ffi.cdef [[
    typedef struct {
        uint32_t cb;
        char DeviceName[32];
        char DeviceString[128];
        uint32_t StateFlags;
        char DeviceID[128];
        char DeviceKey[128];
    } DISPLAY_DEVICE;
    int EnumDisplayDevicesA(const char* lpDevice, int iDevNum, DISPLAY_DEVICE* lpDisplayDevice , unsigned long dwFlags);
]]

local device = ffi.new("DISPLAY_DEVICE")
device.cb = ffi.sizeof("DISPLAY_DEVICE")
if ffi.C.EnumDisplayDevicesA(nil, 0 --[[device index]], device, 0) ~= 0 and bit.band(device.StateFlags, 1 --[[DISPLAY_DEVICE_ACTIVE]]) ~= 0 then
    local display = ffi.new("DISPLAY_DEVICE")
    display.cb = ffi.sizeof("DISPLAY_DEVICE")
    if ffi.C.EnumDisplayDevicesA(device.DeviceName, 0 --[[device index]], display, 0) ~= 0 and bit.band(display.StateFlags, 1 --[[DISPLAY_DEVICE_ACTIVE]]) ~= 0 then
        print('К пк подключён хотя бы 1 монитор')
    else
        print('Мониторы не найдены')
    end
else
    print('Не найден ни 1 адаптор дисплея')
end
Код:
DeviceName - \\.\DISPLAY1\Monitor0
DeviceString - Generic PnP Monitor
StateFlags - 3
DeviceID - MONITOR\ACR06D7\{4d36e96e-e325-11ce-bfc1-08002be10318}\0002
DeviceKey - \Registry\Machine\System\CurrentControlSet\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0002
 
Последнее редактирование:
  • Вау
Реакции: flwr и ChromiusJ