Delphi调用EnumDisplayDevicesA获取显示器名称返回乱码如何解决
问题根源
你调用的是ANSI版本的EnumDisplayDevicesA函数,但结构体里的字符成员全部定义为WideChar(Unicode字符类型),两种字符编码不匹配,读取返回值时就会出现乱码。
修复方案
推荐直接使用Windows原生Unicode版本的EnumDisplayDevicesW函数,避免编码转换问题,需要修改的地方如下:
- 修正类型定义错误:原有自定义的
LPCSTR、PLPCSTR类型不符合Windows API规范,直接替换为Delphi原生的PWideChar即可 - 将外部函数声明从
EnumDisplayDevicesA改为EnumDisplayDevicesW - 修正函数调用时的参数传值方式
修正后完整代码
program Monitor; {$APPTYPE CONSOLE} uses System.SysUtils; const user32 = 'user32.dll'; type PDISPLAY_DEVICE = ^DISPLAY_DEVICE; DISPLAY_DEVICE = packed record cb: Cardinal; deviceName: array[0..31] of WideChar; deviceString: array[0..127] of WideChar; stateFlags: Cardinal; deviceID: array[0..127] of WideChar; deviceKey: array[0..127] of WideChar; end; function EnumDisplayDevicesW(lpDevice: PWideChar; iDevNum: Cardinal; lpDisplayDevice: PDISPLAY_DEVICE; dwFlags: Cardinal): LongBool; stdcall; external user32; procedure PrintMonitorNames(); var LDisplayDevice: DISPLAY_DEVICE; LDeviceIndex: Integer; LMonitorIndex: Integer; LDeviceName: string; begin LDisplayDevice.cb := Sizeof(LDisplayDevice); LDeviceIndex := 0; while EnumDisplayDevicesW(nil, LDeviceIndex, @LDisplayDevice, 0) do begin LDeviceName := LDisplayDevice.deviceName; Writeln('Device name: ' + LDeviceName); LMonitorIndex := 0; // 枚举该设备下的显示器 while EnumDisplayDevicesW(PWideChar(LDeviceName), LMonitorIndex, @LDisplayDevice, 0) do begin Writeln(string(LDisplayDevice.deviceName) + ' ' + string(LDisplayDevice.deviceString)); Inc(LMonitorIndex); end; Inc(LDeviceIndex); end; end; var LDummy: string; begin Writeln('START'); PrintMonitorNames(); Writeln('FINISH'); Readln(LDummy); end.
补充说明
如果你一定要使用ANSI版本的EnumDisplayDevicesA,只需要把结构体中所有WideChar改为AnsiChar,函数参数的指针类型改为PAnsiChar即可,但ANSI版本在非英文系统下容易出现编码问题,不推荐使用。
内容的提问来源于stack exchange,提问作者Matteo Pasini
相关产品推荐
相关产品推荐

