2014/8/6

【C#】設定/查詢螢幕背光

  為了要能用C#控制螢幕背光,跟CreateFileDeviceIoControl函數奮戰大半天,一直搞不定DeviceIoControl函數使用,後來幸運的在網路上找到有人寫好class可以直接調用,之後有需要用到DeviceIoControl函數功能也能參考這class的做法。

調用方法很簡單:
1
2
3
LCDBrightness lcd = new LCDBrightness();
lcd.SetBrightness(100);                                 // Set backlight full on
LCDBrightness.Brightness value = lcd.GetBrightness();   // Query backlight value

原始class內容為:
  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
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
/// <summary>
/// Permet de contrA’ler la luminositAc de l'Accran LCD (sous Windows XP SP2 et ultAcrieur)
/// </summary>
/// <remarks>Sous rAcserve que le driver de la carte graphique et/ou de l'Accran supporte cette interface</remarks>
namespace LCDBrightness
{
  public class LCDBrightness
  {
    //Ouvre un fichier ou un pAcriphAcrique
    [DllImport("kernel32")]
    private static extern IntPtr CreateFile (
        string lpFileName,
        uint dwDesiredAccess,
        int dwShareMode,
        IntPtr lpSecurityAttributes,
        int dwCreationDisposition,
        int dwFlagsAndAttributes,
        IntPtr hTemplateFile);

    //accA‥s en lecture, partagAc et ouverture uniquement d'un pAcriphAcrique existant
    private const uint GENERIC_READ = 0x80000000U;
    private const int SHARE_ALL = 0x7;
    private const int OPEN_EXISTING = 0x3;

    //indique l'Acclairage en mode d'alimentation AC ou DC ou les deux
    private const int DISPLAYPOLICY_AC = 1;
    private const int DISPLAYPOLICY_DC = 2;
    private const int DISPLAYPOLICY_BOTH = DISPLAYPOLICY_AC | DISPLAYPOLICY_DC;

    /// <summary>
    /// Indique les niveaux d'Acclairage en fonction du mode d'alimentation
    /// </summary>
    /// <remarks></remarks>
    public class Brightness
    {
      /// <summary>
      /// Eclairage en mode Alimentation
      /// </summary>
      /// <remarks></remarks>
      public byte AC;
      /// <summary>
      /// Eclairage en mode Batterie
      /// </summary>
      /// <remarks></remarks>
      public byte DC;
    }

    /// <summary>
    /// Contient les donnAces brutes des niveaux d'Acclairage
    /// </summary>
    /// <remarks></remarks>
    private struct DISPLAY_BRIGHTNESS
    {
      public byte ucDisplayPolicy;
      public byte ucACBrightness;
      public byte ucDCBrightness;
    }

    //envoie une requAate A  un pAcriphAcrique
    [DllImport("kernel32")]
    private static extern bool DeviceIoControl (
        IntPtr hDevice,
        int dwIoControlCode,
        ref DISPLAY_BRIGHTNESS lpInBuffer,
        int nInBufferSize,
        IntPtr lpOutBuffer,
        int nOutBufferSize,
        ref int lpBytesReturned,
        IntPtr lpOverlapped);
    [DllImport("kernel32")]
    private static extern bool DeviceIoControl (
        IntPtr hDevice,
        int dwIoControlCode,
        IntPtr lpInBuffer,
        int nInBufferSize,
        ref DISPLAY_BRIGHTNESS lpOutBuffer,
        int nOutBufferSize,
        ref int lpBytesReturned,
        IntPtr lpOverlapped);
    [DllImport("kernel32")]
    private static extern bool DeviceIoControl (
        IntPtr hDevice,
        int dwIoControlCode,
        IntPtr lpInBuffer,
        int nInBufferSize,
        [MarshalAs(UnmanagedType.LPArray)] byte[] lpOutBuffer,
        int nOutBufferSize,
        ref int lpBytesReturned,
        IntPtr lpOverlapped);

    //ferme un fichier ou un pAcriphAcrique
    [DllImport("kernel32")]
    private static extern int CloseHandle(IntPtr hObject);

#region IOCTL
    private const int FILE_DEVICE_VIDEO = 0x23;

    private const int FILE_ANY_ACCESS = 0;
    private const int FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS;

    private const int METHOD_BUFFERED = 0;
    private const int METHOD_NEITHER = 3;

    private const int ERROR_INSUFFICIENT_BUFFER = 122;

    /// <summary>
    /// GA‥re la dAcfinition d'un code de requAate d'un pAcriphAcrique en fonction de ses catAcgories
    /// </summary>
    /// <param name="dwDeviceType">Type de pAcriphAcrique</param>
    /// <param name="dwFunction">RequAate</param>
    /// <param name="dwMethod">MActhode de la requAate</param>
    /// <param name="dwAccess">Mode d'accA‥s</param>
    /// <returns></returns>
    /// <remarks></remarks>
    private static int CTL_CODE(int dwDeviceType, int dwFunction, int dwMethod, int dwAccess)
    {
      return ((dwDeviceType) << 16) | ((dwAccess) << 14) | ((dwFunction) << 2) | (dwMethod);
    }

    //requAate de lecture des niveaux d'Aclcairage supportAcs
    private static int IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS = CTL_CODE(FILE_DEVICE_VIDEO, 293, METHOD_BUFFERED, FILE_ANY_ACCESS);
    //requAate de lecture des niveaux d'Acclairage en cours
    private static int IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS = CTL_CODE(FILE_DEVICE_VIDEO, 294, METHOD_BUFFERED, FILE_ANY_ACCESS);
    //requAate de dAcfinition des niveaux d'Acclairage en cours
    private static int IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS = CTL_CODE(FILE_DEVICE_VIDEO, 295, METHOD_BUFFERED, FILE_ANY_ACCESS);
#endregion

    /// <summary>
    /// Ouvre un handle vers le pAcriphAcrique LCD
    /// </summary>
    /// <returns></returns>
    /// <remarks></remarks>
    private IntPtr OpenLCD()
    {
      //ouverture en lecture partagAce
      return CreateFile("\\\\.\\LCD", GENERIC_READ, SHARE_ALL, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
    }

    private byte[] mBrightness = null;
    /// <summary>
    /// Renvoie la liste des niveaux d'Acclairage supportAcs
    /// </summary>
    /// <value></value>
    /// <returns></returns>
    /// <remarks></remarks>
    public byte[] SupportedBrightness {
      get {
        if (mBrightness == null) {
          int lpRet=0;
          byte[] ret;
          //essaie d'ouvrir le LCD
          IntPtr pDisplay = OpenLCD();
          //si erreur, probablement pas un portable
          if (pDisplay != new IntPtr(-1)) {
              ret = new byte[256];

            //envoie la requAate des niveaux supportAcs
            if (DeviceIoControl(pDisplay, IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS, IntPtr.Zero, 0, ret, 256, ref lpRet, IntPtr.Zero)) {
              //rAccupA‥re un tableau d'octet contenant les niveaux
                mBrightness = new byte[lpRet];

              for (int i = 0; i < lpRet; i++) {
                mBrightness[i] = ret[i];
              }
            }

            CloseHandle(pDisplay);
          }
        }
        return mBrightness;
      }
    }

    /// <summary>
    /// Renvoie l'Acclairage en cours
    /// </summary>
    /// <returns>Eclairage en cours par modes d'alimentation</returns>
    /// <remarks></remarks>
    public Brightness GetBrightness()
    {
      int lpRet=0;
      Brightness ret = null;
      //essaie d'ouvrir le LCD
      IntPtr pDisplay = OpenLCD();
      //si erreur, probablement pas un portable
      if (pDisplay == new IntPtr(-1))
        return null;

      //envoie la requAate de lecture de l'Acclairage en cours
      DISPLAY_BRIGHTNESS pBrightness = new DISPLAY_BRIGHTNESS();
      if (DeviceIoControl(pDisplay, IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS, IntPtr.Zero, 0, ref pBrightness, Marshal.SizeOf(typeof(DISPLAY_BRIGHTNESS)), ref lpRet, IntPtr.Zero)) {
        //si OK, rAccupA‥re la valeur pour AC/Alimentation et DC/Batterie
        ret = new Brightness();
        ret.AC = pBrightness.ucACBrightness;
        ret.DC = pBrightness.ucDCBrightness;
      }

      CloseHandle(pDisplay);

      return ret;
    }

    /// <summary>
    /// DAcfinit l'Acclairage A  la mAame valeur pour les deux modes d'alimentation
    /// </summary>
    /// <param name="brightness">Niveau d'Acclairage</param>
    /// <returns>true si rAcussi, false sinon</returns>
    /// <remarks></remarks>
    public bool SetBrightness(int brightness)
    {
      return SetBrightness(brightness, brightness);
    }

    /// <summary>
    /// DAcfinit l'Acclairage par mode d'alimentation
    /// </summary>
    /// <param name="acBrightness">Niveau AC/Alimentation</param>
    /// <param name="dcBrightness">Niveau DC/Batterie</param>
    /// <returns>true si rAcussi, false sinon</returns>
    /// <remarks></remarks>
    public bool SetBrightness(int acBrightness, int dcBrightness)
    {
      bool ret;
      int lpRet=0;
      //essaie d'ouvrir le LCD
      IntPtr pDisplay = OpenLCD();
      //si erreur, probablement pas un portable
      if (pDisplay == new IntPtr(-1))
        return false;

      //remplit la structure et informe que l'on dAcfinit les deux valeurs
      DISPLAY_BRIGHTNESS pBrightness = new DISPLAY_BRIGHTNESS();
      pBrightness.ucACBrightness = (byte)(acBrightness & 0xFF);
      pBrightness.ucDCBrightness = (byte)(dcBrightness & 0xFF);
      pBrightness.ucDisplayPolicy = DISPLAYPOLICY_BOTH;

      //envoie la requAate de dAcfinition de l'Acclairage au pAcriphAcrique LCD
      ret = DeviceIoControl(pDisplay, IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS, ref pBrightness, Marshal.SizeOf(pBrightness), IntPtr.Zero, 0, ref lpRet, IntPtr.Zero);

      CloseHandle(pDisplay);

      return ret;
    }
  }
}

參考原始出處:http://codes-sources.commentcamarche.net/source/view/53617/1259513#browser

Keyword:C#, Windows, Backlight

沒有留言:

張貼留言