使用 Delphi 中的 EnumDisplayDevices 打印显示器名称
Print the monitor's name with EnumDisplayDevices in Delphi
我需要阅读一些有关通过 EnumDisplayDevicesA 功能连接的监视器的信息。
我试图将以下用c++编写的example转换为delphi,但是当我尝试从PDISPLAY_DEVICEA结构[=12]中读取设备名称时出现问题=]因为它只有returns个汉字。
我认为这是与字符编码有关的问题,但我不知道如何解决它。
我的源代码:
program Monitor;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
const
user32 = 'user32.dll';
type
LONG = LongInt;
BOOL = LongBool;
PDISPLAY_DEVICE = ^DISPLAY_DEVICE;
LPCSTR = array[0..128 - 1] of WideChar;
PLPCSTR = ^LPCSTR;
//https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-display_devicea
DISPLAY_DEVICE = packed record
cb: Cardinal;
deviceName: array[0..32 - 1] of WideChar;
deviceString: array[0..128 - 1] of WideChar;
stateFlags: Cardinal;
deviceID: array[0..128 - 1] of WideChar;
deviceKey: array[0..128 - 1] of WideChar;
end;
//https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesa
function EnumDisplayDevicesA(APCSTR: PLPCSTR; iDevNum: Cardinal; PDISPLAY_DEVICEA: PDISPLAY_DEVICE; dwFlags: Cardinal): BOOL; stdcall; external user32;
procedure PrintMonitorNames();
var
LDisplayDevice: DISPLAY_DEVICE;
LDeviceIndex: Integer;
LMonitorIndex: Integer;
LDeviceName: string;
begin
LDisplayDevice.cb := Sizeof(LDisplayDevice);
LDeviceIndex := 0;
while EnumDisplayDevicesA(nil, LDeviceIndex, @LDisplayDevice, 0) do
begin
LDeviceName := LDisplayDevice.deviceName;
Writeln('Device name: ' + LDeviceName);
LMonitorIndex := 0;
while EnumDisplayDevicesA(@LDeviceName, LMonitorIndex, @LDisplayDevice, 0) do
begin
Writeln(StrPas(LDisplayDevice.deviceName) + ' ' + StrPas(LDisplayDevice.deviceString));
Inc(LMonitorIndex);
end;
Inc(LDeviceIndex);
end;
end;
var
LDummy: string;
begin
Writeln('START');
PrintMonitorNames();
Writeln('FINISH');
Readln(LDummy);
end.
您正在混合使用 ANSI 和 Unicode。
EnumDisplayDevices
函数存在两个版本:
EnumDisplayDevicesA
这是(旧版)ANSI。
EnumDisplayDevicesW
这是 Unicode。
您调用的是 ANSI 版本 EnumDisplayDevicesA
,但使用的是 DISPLAY_DEVICE
的 Unicode 版本。所以你需要使用 EnumDisplayDevicesW
来代替。
这种API函数在W版和A版中都存在的现象在WindowsAPI中无处不在,所以上面的说法很笼统。
由于这种编码不匹配导致您得到中文文本的事实也是 very well known。
说了这么多,你根本不需要自己声明EnumDisplayDevices
。你需要的一切都已经存在于 Delphi RTL 的 Windows.pas
单元中,就像我向你展示的那样 :
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows;
begin
var dd, md: TDisplayDevice;
FillChar(dd, SizeOf(dd), 0);
dd.cb := SizeOf(dd);
FillChar(md, SizeOf(md), 0);
md.cb := SizeOf(md);
var i := 0;
while EnumDisplayDevices(nil, i, dd, 0) do
begin
var j := 0;
while EnumDisplayDevices(@dd.DeviceName[0], j, md, 0) do
begin
Writeln(md.DeviceString);
Inc(j);
end;
Inc(i);
end;
Readln;
end.
注意 MSDN 是这样说的:
The winuser.h header defines EnumDisplayDevices as an alias which automatically selects the ANSI or Unicode version of this function based on the definition of the UNICODE preprocessor constant.
同样的评论适用于 Delphi RTL 的 Windows.pas
。
我需要阅读一些有关通过 EnumDisplayDevicesA 功能连接的监视器的信息。
我试图将以下用c++编写的example转换为delphi,但是当我尝试从PDISPLAY_DEVICEA结构[=12]中读取设备名称时出现问题=]因为它只有returns个汉字。 我认为这是与字符编码有关的问题,但我不知道如何解决它。
我的源代码:
program Monitor;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
const
user32 = 'user32.dll';
type
LONG = LongInt;
BOOL = LongBool;
PDISPLAY_DEVICE = ^DISPLAY_DEVICE;
LPCSTR = array[0..128 - 1] of WideChar;
PLPCSTR = ^LPCSTR;
//https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-display_devicea
DISPLAY_DEVICE = packed record
cb: Cardinal;
deviceName: array[0..32 - 1] of WideChar;
deviceString: array[0..128 - 1] of WideChar;
stateFlags: Cardinal;
deviceID: array[0..128 - 1] of WideChar;
deviceKey: array[0..128 - 1] of WideChar;
end;
//https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesa
function EnumDisplayDevicesA(APCSTR: PLPCSTR; iDevNum: Cardinal; PDISPLAY_DEVICEA: PDISPLAY_DEVICE; dwFlags: Cardinal): BOOL; stdcall; external user32;
procedure PrintMonitorNames();
var
LDisplayDevice: DISPLAY_DEVICE;
LDeviceIndex: Integer;
LMonitorIndex: Integer;
LDeviceName: string;
begin
LDisplayDevice.cb := Sizeof(LDisplayDevice);
LDeviceIndex := 0;
while EnumDisplayDevicesA(nil, LDeviceIndex, @LDisplayDevice, 0) do
begin
LDeviceName := LDisplayDevice.deviceName;
Writeln('Device name: ' + LDeviceName);
LMonitorIndex := 0;
while EnumDisplayDevicesA(@LDeviceName, LMonitorIndex, @LDisplayDevice, 0) do
begin
Writeln(StrPas(LDisplayDevice.deviceName) + ' ' + StrPas(LDisplayDevice.deviceString));
Inc(LMonitorIndex);
end;
Inc(LDeviceIndex);
end;
end;
var
LDummy: string;
begin
Writeln('START');
PrintMonitorNames();
Writeln('FINISH');
Readln(LDummy);
end.
您正在混合使用 ANSI 和 Unicode。
EnumDisplayDevices
函数存在两个版本:
EnumDisplayDevicesA
这是(旧版)ANSI。EnumDisplayDevicesW
这是 Unicode。
您调用的是 ANSI 版本 EnumDisplayDevicesA
,但使用的是 DISPLAY_DEVICE
的 Unicode 版本。所以你需要使用 EnumDisplayDevicesW
来代替。
这种API函数在W版和A版中都存在的现象在WindowsAPI中无处不在,所以上面的说法很笼统。
由于这种编码不匹配导致您得到中文文本的事实也是 very well known。
说了这么多,你根本不需要自己声明EnumDisplayDevices
。你需要的一切都已经存在于 Delphi RTL 的 Windows.pas
单元中,就像我向你展示的那样
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows;
begin
var dd, md: TDisplayDevice;
FillChar(dd, SizeOf(dd), 0);
dd.cb := SizeOf(dd);
FillChar(md, SizeOf(md), 0);
md.cb := SizeOf(md);
var i := 0;
while EnumDisplayDevices(nil, i, dd, 0) do
begin
var j := 0;
while EnumDisplayDevices(@dd.DeviceName[0], j, md, 0) do
begin
Writeln(md.DeviceString);
Inc(j);
end;
Inc(i);
end;
Readln;
end.
注意 MSDN 是这样说的:
The winuser.h header defines EnumDisplayDevices as an alias which automatically selects the ANSI or Unicode version of this function based on the definition of the UNICODE preprocessor constant.
同样的评论适用于 Delphi RTL 的 Windows.pas
。