利用Nvidia的API设置数字振动数值源码_显示器亮度、对比度等设置源码

开始是一位朋友有这个需求,他给了我一个英伟达官网的开发包,名字是:R410-developer.zip(诸位可以自己到英伟达官网下载),里面提供了一些示例,包含自定义分辨率、显示器颜色设置等,但是显示器色彩设置的例子一致没有跑通,而且我也没有找到哪个参数是可以设置数字振动值的,所以憋屈了很多天。但直到看到了一个 AHK 版本实现的设置工具通过代码发现,其实实现方法是通过 nvapi.dll 动态库导出的一个查询函数地址的方法,将指定接口导出来执行具体业务。在加上在 github 上搜索的各类示例,最终实现了这个功能,下面详细介绍实现步骤。
用Nvidia的API设置数字振动数值

  1. 需要的方法和结构
    设置数字振动数值需要先通过 nvapi.dll 导出的 NvAPI_QueryInterface_t 方法获取 NvAPI_Initialize_t 方法来初始化 NvAPI。然后依次获取显示器句柄、获取当前显示器数字振动值、设置数字振动值的函数地址,他们的声明分别对应如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 查询在 nvapi.dll 中函数的地址方法函数声明
    typedef int*(*NvAPI_QueryInterface_t)(unsigned int offset);
    // 初始化 NvAPI 的方法
    typedef int(*NvAPI_Initialize_t)();
    // 根据 ID 枚举显示器句柄的方法
    typedef int(*NvAPI_EnumNvidiaDisplayHandle_t)(int thisEnum, int* pNvDispHandle);
    // 获取数字振动当前值
    typedef int(*NvAPI_GetDVCInfoEx_t)(int hNvDisplay, int outputId, NV_DISPLAY_DVC_INFO_EX* pDVCInfo);
    // 设置数字振动值
    typedef int(*NvAPI_SetDVCLevelEx_t)(int hNvDisplay, int outputId, NV_DISPLAY_DVC_INFO_EX* pDVCInfo);
    其中设置和获取数字振动值需要一个结构体 NV_DISPLAY_DVC_INFO_EX,其声明如下:
    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct
    {
    unsigned int version; // 结构体版本
    int currentLevel; // 当前级别
    int minLevel; // 最低级别
    int maxLevel; // 最高级别
    int defaultLevel; // 默认级别
    } NV_DISPLAY_DVC_INFO_EX, *PNV_DISPLAY_DVC_INFO_EX;
  2. 获取各个接口地址
    我们首先 Load nvapi.dll 然后得到 nvapi_QueryInterface 方法的地址,然后通过 nvapi_QueryInterface 方法查询另外一些接口的地址。如下所示:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    bool NvController::Initialize()
    {
    hModule = LoadLibraryW(TEXT("nvapi.dll"));
    if (hModule == nullptr)
    {
    std::cerr << "Failed to load nvapi.dll." << std::endl;
    return false;
    }

    NvAPI_QueryInterface = (NvAPI_QueryInterface_t)GetProcAddress(hModule, "nvapi_QueryInterface");
    NvAPI_Initialize = (NvAPI_Initialize_t)(*NvAPI_QueryInterface)(_NvAPI_Initialize);
    NvAPI_EnumNvidiaDisplayHandle = (NvAPI_EnumNvidiaDisplayHandle_t)(*NvAPI_QueryInterface)(_NvAPI_EnumNvidiaDisplayHandle);
    NvAPI_GetDVCInfoEx = (NvAPI_GetDVCInfoEx_t)(*NvAPI_QueryInterface)(_NvAPI_GetDVCInfoEx);
    NvAPI_SetDVCLevelEx = (NvAPI_SetDVCLevelEx_t)(*NvAPI_QueryInterface)(_NvAPI_SetDVCLevelEx);

    _NvAPI_Status status = (_NvAPI_Status)(*NvAPI_Initialize)();
    if (status != NVAPI_OK)
    {
    std::cerr << "NvAPI initialization failed." << std::endl;
    return false;
    }

    return true;
    }
    其中以下划线开头的枚举名字是每个函数在 dll 中的对应地址,这些是写死的,如下所示:
    1
    2
    3
    4
    5
    6
    7
    8
    enum NvAPIs
    {
    _NvAPI_Initialize = 0x150E828,
    _NvAPI_EnumNvidiaDisplayHandle = 0x9ABDD40D,
    _NvAPI_GetAssociatedNvidiaDisplayName = 0x22A78B05,
    _NvAPI_GetDVCInfoEx = 0x0E45002D,
    _NvAPI_SetDVCLevelEx = 0x4A82C2B1
    };
    你可能会问,你怎么知道这些函数地址的?其实我也是搜索到的,也看了以前 NvAPI 老版本提供的代码,可以搜索到相关痕迹。点击查看此文件里面有完整的所有函数地址。
  3. 获取和设置数字振动
    得到了各个函数的地址,我们就可以设置数字振动值了,代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    bool NvController::SetDVCLevelEx(int nDisp, int level)
    {
    int NvDispHandle;
    if (EnumNvidiaDisplayHandle(nDisp, &NvDispHandle) != 0)
    {
    NV_DISPLAY_DVC_INFO_EX oldInfo = GetDvcInfoEx(nDisp);

    NV_DISPLAY_DVC_INFO_EX info;
    info.version = oldInfo.version;
    info.currentLevel = level;
    info.minLevel = oldInfo.minLevel;
    info.maxLevel = oldInfo.maxLevel;
    info.defaultLevel = oldInfo.defaultLevel;

    _NvAPI_Status status = (_NvAPI_Status)(*NvAPI_SetDVCLevelEx)(NvDispHandle, 0, &info);
    if (status != NVAPI_OK)
    {
    return false;
    }

    return true;
    }

    return false;
    }
    我们首先获得用户传入的显示器编号所对应的句柄,然后根据这个句柄获取当前数字振动的数值,然后修改其 currentLevel 成员数值来设置数字振动效果。这样处理后就可以使用了。
    完整代码参考地址:https://github.com/nmgwddj/nvapi-example

转载自https://cloud.tencent.com/developer/article/1371564
4. 屏幕亮度,对比度获取和调节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
bool set_screen_brightness(long val)
{
HWND hDesktopWnd = GetDesktopWindow();
HMONITOR hMonitor = MonitorFromWindow(hDesktopWnd, MONITOR_DEFAULTTOPRIMARY);
DWORD cPhysicalMonitors = 0;
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors))
return false;

LPPHYSICAL_MONITOR pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));
if (pPhysicalMonitors)
{
GetPhysicalMonitorsFromHMONITOR(hMonitor, cPhysicalMonitors, pPhysicalMonitors);

//设置屏幕亮度
SetMonitorBrightness(pPhysicalMonitors->hPhysicalMonitor, val);
//设置屏幕对比度
//SetMonitorContrast(pPhysicalMonitors->hPhysicalMonitor, val);
// Close the monitor handles.
DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors);

// Free the array.
free(pPhysicalMonitors);

}
return true;
}

long get_screen_brightness()
{
long lret = -1;
HWND hDesktopWnd = GetDesktopWindow();
HMONITOR hMonitor = MonitorFromWindow(hDesktopWnd, MONITOR_DEFAULTTOPRIMARY);
DWORD dwMin = 0, dwMax = 0, dwCur = 0;
DWORD cPhysicalMonitors = 0;
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors))
return false;

LPPHYSICAL_MONITOR pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));
if (pPhysicalMonitors)
{
GetPhysicalMonitorsFromHMONITOR(hMonitor, cPhysicalMonitors, pPhysicalMonitors);

//获取屏幕对比度
//if (GetMonitorContrast(pPhysicalMonitors->hPhysicalMonitor, &dwMin, &dwCur, &dwMax))
//获取屏幕亮度
if (GetMonitorBrightness(pPhysicalMonitors->hPhysicalMonitor, &dwMin, &dwCur, &dwMax))
{
lret = dwCur;
}
//SetMonitorContrast(pPhysicalMonitors->hPhysicalMonitor, val);

// Close the monitor handles.
DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors);

// Free the array.
free(pPhysicalMonitors);

}
return lret;
}
  1. 屏幕色彩灰度调节(Gamma调节)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    // #pragma pack(push, 4)
    // typedef struct _tagD3dGammaramp_t
    // {
    // WORD red[256];
    // WORD green[256];
    // WORD blue[256];
    // }D3DGAMMARAMP, *LPD3DGAMMARAMP;
    // #pragma pack(pop)

    class CScreenDC
    {
    public:
    CScreenDC(){ m_hdc = GetDC(NULL); }
    ~CScreenDC(){ if (m_hdc) ReleaseDC(NULL, m_hdc); m_hdc = NULL; }
    operator HDC(){ return m_hdc; }
    private:
    HDC m_hdc;
    };

    bool set_screen_gray(long val)
    {
    //HDC的对比度
    val = min(100, val);
    val = max(0, val);
    val = val*128.0 / 100;
    /*
    bright >=0 && bright <= 128
    */
    CScreenDC hScreenDc;
    D3DGAMMARAMP Ramp = { 0 };
    BOOL bret = GetDeviceGammaRamp(hScreenDc, &Ramp);
    if (!bret) return false;

    for (int iIndex = 0; iIndex < 256; iIndex++)
    {
    //bright 为什么需要+128,因为当 bring < 128 的时候效果同bright = 0
    Ramp.red[iIndex] = min(65535, iIndex * (val + 128));
    Ramp.green[iIndex] = min(65535, iIndex * (val + 128));
    Ramp.blue[iIndex] = min(65535, iIndex * (val + 128));
    }
    bret = SetDeviceGammaRamp(hScreenDc, &Ramp);
    return bret ? true:false;
    }

    long get_screen_gray()
    {
    CScreenDC hScreenDc;
    D3DGAMMARAMP Ramp = { 0 };
    BOOL bret = GetDeviceGammaRamp(hScreenDc, &Ramp);
    if (!bret) return -1;
    long bright = Ramp.red[1] - 128;

    bright = bright * 100.0 / 128;
    bright = min(100, bright);
    bright = max(0, bright);

    return bright;
    }
  2. 鼠标移动速度调节
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    bool set_mousemove_speed(long val)
    {
    //其接收范围在1(最慢)和20(最快)之间的值。值为10是
    val = min(20, val);
    val = max(1, val);

    BOOL bret = SystemParametersInfo(SPI_SETMOUSESPEED, 0, (LPVOID)val, SPIF_UPDATEINIFILE || SPIF_SENDCHANGE || SPIF_SENDWININICHANGE);
    if (!bret) return false;
    return true;
    }

    long get_mousemove_speed()
    {
    int nSpeed = 0;
    BOOL bret = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &nSpeed, 0);
    if (!bret) return -1;
    return nSpeed;
    }
  3. 鼠标双击速度调节
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //方法1:SystemParametersInfo(SPI_SETDOUBLECLICKTIME....
    bool set_mousedbclick_speed(long val)
    {
    //最快200ms 最慢 900ms 间隔70ms
    //SPI_SETDOUBLECLICKTIME

    val = 550 - (val - 10) * 35;
    val = min(900, val);
    val = max(200, val);
    BOOL bret = SetDoubleClickTime(val);
    if (!bret) return false;
    return true;
    }

    UINT get_mousedbclick_speed()
    {
    UINT ival = GetDoubleClickTime();
    ival = (ival - 550) / 35 + 10;
    return ival;
    }
    转自 https://blog.csdn.net/CAir2/article/details/103897288

华夏网盟的成品下载 链接:https://share.weiyun.com/GJUzRJLE 密码:6jaisr

-------------本文已结束赏个小钱吧-------------
×

感谢您的支持,我们会一直保持!

扫码支持
请土豪扫码随意打赏

打开微信扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

64.7K

相关文章推荐