飞道的博客

c#配合c++调节屏幕亮度,非伽马以及RGB方案

287人阅读  评论(0)

文章开头感谢国内唯一(搜索前几页能找到的)完善了背光调节API资料的独苗 :https://blog.csdn.net/weixin_34111819/article/details/86328019

PS:他代码的主干对了,细节处有很多相对于VS的错误,毕竟是DEV写的,这样很难用作工程。


  
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <windows.h>
  5. #include <iostream>
  6. #include <Ntddvdeo.h>
  7. using namespace std;
  8. #define IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS CTL_CODE(FILE_DEVICE_VIDEO, 0x125, METHOD_BUFFERED, FILE_ANY_ACCESS)
  9. #define IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS CTL_CODE(FILE_DEVICE_VIDEO, 0x126, METHOD_BUFFERED, FILE_ANY_ACCESS)
  10. #define IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS CTL_CODE(FILE_DEVICE_VIDEO, 0x127, METHOD_BUFFERED, FILE_ANY_ACCESS)
  11. int setBrightness(int level)
  12. {
  13. HANDLE h;
  14. DWORD nOutBufferSize = 256;
  15. BYTE SupportedBrightness[ 256];
  16. DWORD g_supportedLevelCount;
  17. DISPLAY_BRIGHTNESS DisplayBrightness;
  18. memset(SupportedBrightness, 0, sizeof(SupportedBrightness));
  19. /* use createfile function to open lcd.
  20. * url from microsoft about IOCTL code.
  21. * http://msdn.microsoft.com/en-us/library/windows/desktop/aa372703%28v=vs.85%29.aspx
  22. */
  23. /*
  24. * char* 和 wchar_t* 互相转换参考博客
  25. * https://www.cnblogs.com/icqw/p/4614877.html
  26. */
  27. /*
  28. * c++代码参考博客
  29. * https://blog.csdn.net/weixin_34111819/article/details/86328019
  30. */
  31. char temchar[] = "\\\\.\\LCD";
  32. char* szSour = temchar;
  33. WCHAR Temp[ 128] = { 0 };
  34. mbstowcs(Temp, szSour, strlen(szSour));
  35. h = CreateFile(Temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
  36. if (h == INVALID_HANDLE_VALUE) {
  37. printf( "Open \\\\.\\LCD error");
  38. exit( 1);
  39. }
  40. /* Query for display supported level */
  41. if (!DeviceIoControl(h, IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS, NULL, 0, SupportedBrightness, nOutBufferSize, &g_supportedLevelCount, NULL)) {
  42. printf( "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS error - %d, - buffer: %d ", g_supportedLevelCount, nOutBufferSize);
  43. exit( 1);
  44. }
  45. if (g_supportedLevelCount == 0) /* 0 means not supported */
  46. {
  47. printf( "\nLCD not support LEVEL COUNT", g_supportedLevelCount);
  48. exit( 1);
  49. }
  50. DisplayBrightness.ucDisplayPolicy = 0;
  51. DisplayBrightness.ucACBrightness = level;
  52. DisplayBrightness.ucDCBrightness = level;
  53. /* Set display backlight level */
  54. nOutBufferSize = sizeof(DisplayBrightness);
  55. if (!DeviceIoControl(h, IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS, (DISPLAY_BRIGHTNESS*)&DisplayBrightness, nOutBufferSize, NULL, 0, &nOutBufferSize, NULL)) {
  56. printf( "IOCTL_VIDEO_SET_SUPPORTED_BRIGHTNESS error - %d, - buffer: %d ", g_supportedLevelCount, nOutBufferSize);
  57. exit( 1);
  58. }
  59. Sleep( 500); /* delay for some time while wmi event changed */
  60. nOutBufferSize = sizeof(DisplayBrightness);
  61. if (!DeviceIoControl(h, IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS, NULL, 0, (DISPLAY_BRIGHTNESS*)&DisplayBrightness, nOutBufferSize, &nOutBufferSize, NULL)) {
  62. printf( "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS error - %d, - buffer: %d ", g_supportedLevelCount, nOutBufferSize);
  63. exit( 1);
  64. }
  65. printf( "\nBrightness_AC: %d\nBrightness_DC: %d", DisplayBrightness.ucACBrightness, DisplayBrightness.ucDCBrightness);
  66. }
  67. int main() {
  68. int a;
  69. cin >> a;
  70. setBrightness(a);
  71. return 0;
  72. }

编译环境是VS,众所周知VS对代码的要求相对严格。所以这位大佬的代码有些部分需要修改。在这里我会指出修改地方以及对修改的部分进行解释。

首先#include <Ntddvdeo.h>直接引用就可以了不要加前缀,VS会自动寻找这个头文件的。


  
  1. char temchar[] = "\\\\.\\LCD";
  2. char* szSour = temchar;
  3. WCHAR Temp[ 128] = { 0 };
  4. mbstowcs(Temp, szSour, strlen(szSour));
  5. h = CreateFile(Temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);

其次这里的Temp参数,之前大佬的写法是直接“\\\\.\\LCD”,但是这个参数的位置是填到一个WCHAR类型的参数,所以我们要对其进行转换。在转换的过程中VS不允许使用char*指针指向一个字符串常量,所以我们要先将这个字符串常量赋值给一个字符数组,然后再用指针指向它就行了。转换的方法在另一位大佬的博客中,我在代码中已经作为注释给出地址了(感谢各个前辈们做出的贡献)。

最后我要注明一下,这个int setBrightness(int level)中的level的范围是0到100,虽然大多数情况下调到0也能看清,但是万一呢是吧,最好测试的时候别调到零。

上面的是c++代码现在让我们来做成c#模块。(这个模块文末我会放出连接,有百度云和CSDN两个连接,还有gitHub有全部的源代码)我们的思路是将C++编译成DLL模块,然后由c#引用,并在C#中封装成模块的方式来供C#调用。

下面是c++封装DLL的教程(正在准备材料,还没写完,先存着)

建立DLL工程之后对工程稍作修改,改动如下:

将这一句删掉,因为我们要用到这些极少用的内容。

然后将dllmain.cpp的内容改为如下内容


  
  1. // dllmain.cpp : 定义 DLL 应用程序的入口点。
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #include "pch.h"
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <windows.h>
  7. #include <iostream>
  8. #include <Ntddvdeo.h>
  9. BOOL APIENTRY DllMain(HMODULE hModule,
  10. DWORD ul_reason_for_call,
  11. LPVOID lpReserved
  12. )
  13. {
  14. switch (ul_reason_for_call)
  15. {
  16. case DLL_PROCESS_ATTACH:
  17. case DLL_THREAD_ATTACH:
  18. case DLL_THREAD_DETACH:
  19. case DLL_PROCESS_DETACH:
  20. break;
  21. }
  22. return TRUE;
  23. }
  24. #define IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS CTL_CODE(FILE_DEVICE_VIDEO, 0x125, METHOD_BUFFERED, FILE_ANY_ACCESS)
  25. #define IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS CTL_CODE(FILE_DEVICE_VIDEO, 0x126, METHOD_BUFFERED, FILE_ANY_ACCESS)
  26. #define IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS CTL_CODE(FILE_DEVICE_VIDEO, 0x127, METHOD_BUFFERED, FILE_ANY_ACCESS)
  27. extern "C" _declspec(dllexport) void setBrightness(int level)
  28. {
  29. HANDLE h;
  30. DWORD nOutBufferSize = 256;
  31. BYTE SupportedBrightness[ 256];
  32. DWORD g_supportedLevelCount;
  33. DISPLAY_BRIGHTNESS DisplayBrightness;
  34. memset(SupportedBrightness, 0, sizeof(SupportedBrightness));
  35. /* use createfile function to open lcd.
  36. * url from microsoft about IOCTL code.
  37. * http://msdn.microsoft.com/en-us/library/windows/desktop/aa372703%28v=vs.85%29.aspx
  38. */
  39. /*
  40. * char* 和 wchar_t* 互相转换参考博客
  41. * https://www.cnblogs.com/icqw/p/4614877.html
  42. */
  43. /*
  44. * c++代码参考博客
  45. * https://blog.csdn.net/weixin_34111819/article/details/86328019
  46. */
  47. char temchar[] = "\\\\.\\LCD";
  48. char* szSour = temchar;
  49. WCHAR Temp[ 128] = { 0 };
  50. mbstowcs(Temp, szSour, strlen(szSour));
  51. h = CreateFile(Temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
  52. if (h == INVALID_HANDLE_VALUE) {
  53. printf( "Open \\\\.\\LCD error");
  54. exit( 1);
  55. }
  56. /* Query for display supported level */
  57. if (!DeviceIoControl(h, IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS, NULL, 0, SupportedBrightness, nOutBufferSize, &g_supportedLevelCount, NULL)) {
  58. printf( "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS error - %d, - buffer: %d ", g_supportedLevelCount, nOutBufferSize);
  59. exit( 1);
  60. }
  61. if (g_supportedLevelCount == 0) /* 0 means not supported */
  62. {
  63. printf( "\nLCD not support LEVEL COUNT", g_supportedLevelCount);
  64. exit( 1);
  65. }
  66. DisplayBrightness.ucDisplayPolicy = 0;
  67. DisplayBrightness.ucACBrightness = level;
  68. DisplayBrightness.ucDCBrightness = level;
  69. /* Set display backlight level */
  70. nOutBufferSize = sizeof(DisplayBrightness);
  71. if (!DeviceIoControl(h, IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS, (DISPLAY_BRIGHTNESS*)&DisplayBrightness, nOutBufferSize, NULL, 0, &nOutBufferSize, NULL)) {
  72. printf( "IOCTL_VIDEO_SET_SUPPORTED_BRIGHTNESS error - %d, - buffer: %d ", g_supportedLevelCount, nOutBufferSize);
  73. exit( 1);
  74. }
  75. Sleep( 500); /* delay for some time while wmi event changed */
  76. nOutBufferSize = sizeof(DisplayBrightness);
  77. if (!DeviceIoControl(h, IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS, NULL, 0, (DISPLAY_BRIGHTNESS*)&DisplayBrightness, nOutBufferSize, &nOutBufferSize, NULL)) {
  78. printf( "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS error - %d, - buffer: %d ", g_supportedLevelCount, nOutBufferSize);
  79. exit( 1);
  80. }
  81. printf( "\nBrightness_AC: %d\nBrightness_DC: %d", DisplayBrightness.ucACBrightness, DisplayBrightness.ucDCBrightness);
  82. }

注意这里作为c语言导出DLL是有必要的,否则导出后对外名字可能就改变了,不再是你声明的那个函数名了,会给后面的调用造成一定的困难。


  
  1. extern "C" _declspec(dllexport) void setBrightness(int level)
  2. //这里的C就是C语言形式导出的意思

设置完成之后右键点击如下位置,然后选择生成解决方案。然后右键打开菜单之后选择“在资源管理器中打开”就能找到项目文件夹,然后找到debug文件夹,在文件夹下面就有dll文件,包括dll在内所有文件烤走就能用了。

完成之后开始创建C#版的DLL对c++的DLL进行二次封装

新建完成后,将DLL拖入项目资源,记住这里不能添加引用,非托管类型的DLL没法添加引用。

新建一个类,并填入如下代码


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace BGLight
  8. {
  9. public class ChangeLight
  10. {
  11. [ DllImport("BGLightChangeDLL.dll")]
  12. public static extern void setBrightness(Int32 level);
  13. public void Change(Int32 level)
  14. {
  15. setBrightness(level);
  16. }
  17. }
  18. }

其中下面两句就是引入DLL的语句


  
  1. [ DllImport("BGLightChangeDLL.dll")]
  2. public static extern void setBrightness(Int32 level);

然后同样的步骤生成C#版的DLL。

得到c#版的DLL之后,在其他的c#工程只需要在工程中添加对DLL的引用并using相应的命名空间即可。

c#版:https://download.csdn.net/download/u011471253/15500112

c++版:https://download.csdn.net/download/u011471253/15500113

 


转载:https://blog.csdn.net/u011471253/article/details/114170009
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场