First you must know some monitor doesn't have registered name in windows but if they have a name and you can read it with a program like MultiMonitorTool, So you can read it with Delphi too.
You can read EDID key value from the registry.
Value of EDID key create when monitor installed and can be overwritten by monitor driver.
This program read EDID for the active monitors.
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.Win.Registry, Vcl.ComCtrls, Winapi.MultiMon,
Winapi.Windows, Vcl.Forms, System.Classes, System.StrUtils,
System.Character;
function GetMonitorName(index : Integer) : String;
const
Key = '\SYSTEM\CurrentControlSet\Enum\DISPLAY\';
type
IBMString = type Ansistring(1253);
var
Handle: HMONITOR;
i, j, k : Integer;
Registry: TRegistry;
MonitorName : IBMString;
DispDev : TDisplayDevice;
subKeysNames : TStringList;
MonitorInfo : TMonitorInfoEx;
DeviceIDSplit : TArray<String>;
EDID : array [0 .. 127] of Byte;
DeviceName, DeviceString, DeviceID, DeviceKey, Driver : string;
begin
Result := '';
Handle := Screen.Monitors[index].Handle;
MonitorInfo.cbSize := sizeof(MonitorInfo);
if GetMonitorInfo(Handle, @MonitorInfo) then
begin
DispDev.cb := sizeof(DispDev);
EnumDisplayDevices(@MonitorInfo.szDevice, 0, DispDev, 0);
DeviceName := StrPas(DispDev.DeviceName); //'\\.\DISPLAY1\Monitor0' //This Line Can Be Removed
DeviceString := StrPas(DispDev.DeviceString); //'Generic PnP Monitor' //This Line Can Be Removed
DeviceID := StrPas(DispDev.DeviceID);
DeviceKey := StrPas(DispDev.DeviceKey); //This Line Can Be Removed
DeviceIDSplit := DeviceID.Split(['\']);
if Length(DeviceIDSplit) < 3 then Exit;
Driver := '';
for i := 2 to High(DeviceIDSplit) do
Driver := Driver + '\' + DeviceIDSplit[i];
System.Delete(Driver, 1, 1);
subKeysNames := TStringList.Create;
Registry := TRegistry.Create(KEY_READ);
Registry.RootKey := HKEY_LOCAL_MACHINE;
try
try
Registry.OpenKeyReadOnly(Key);
Registry.GetKeyNames(subKeysNames);
finally
Registry.CloseKey;
end;
if subKeysNames.IndexOf(DeviceIDSplit[1]) < 0 then Exit;
try
Registry.OpenKeyReadOnly(Key + DeviceIDSplit[1]);
Registry.GetKeyNames(subKeysNames);
finally
Registry.CloseKey;
end;
for i := 0 to subKeysNames.Count - 1 do
begin
try
if registry.OpenKeyReadOnly(Key + DeviceIDSplit[1] + '\' + subKeysNames[i]) then
begin
if Registry.ReadString('Driver') <> Driver then Continue;
Registry.CloseKey;
if registry.OpenKeyReadOnly(Key + DeviceIDSplit[1] + '\' + subKeysNames[i] + '\' + 'Device Parameters') then
begin
Registry.ReadBinaryData('EDID', EDID, 128);
Registry.CloseKey;
end;
for j := 0 to 3 do
begin
if (EDID[54 + 18 * j] = 0) and
(EDID[55 + 18 * j] = 0) and
(EDID[56 + 18 * j] = 0) and
(EDID[57 + 18 * j] = $FC) and
(EDID[58 + 18 * j] = 0) then
begin
k := 0;
while (EDID[59 + 18 * j + k] <> $A) and (k < 13) do
Inc(k);
SetString(MonitorName, PAnsiChar(@EDID[59 + 18 * j]), k);
Result := MonitorName;
Break;
end;
end;
end;
finally
Registry.CloseKey;
end;
end;
finally
Registry.Free;
subKeysNames.Free;
end;
end;
end;
var
i : Integer;
begin
for i := 0 to Screen.MonitorCount-1 do
begin
Writeln(GetMonitorName(i));
end;
Readln;
end.
and this program read all of monitor names, some of them may don't have a name.
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.Win.Registry, Vcl.ComCtrls, Winapi.MultiMon,
Winapi.Windows, Vcl.Forms, System.Classes, System.StrUtils,
System.Character;
function GetAllMonitorName : TStrings;
const
Key = '\SYSTEM\CurrentControlSet\Enum\DISPLAY\';
type
IBMString = type Ansistring(1253);
var
Registry: TRegistry;
H, i, j, k : Integer;
MonitorName : IBMString;
EDID : array [0 .. 127] of Byte;
subKeysNames, subKeys : TStringList;
begin
Result := TStringList.Create;
subKeys := TStringList.Create;
subKeysNames := TStringList.Create;
Registry := TRegistry.Create(KEY_READ);
Registry.RootKey := HKEY_LOCAL_MACHINE;
try
try
Registry.OpenKeyReadOnly(Key);
Registry.GetKeyNames(subKeysNames);
finally
Registry.CloseKey;
end;
for h := 0 to subKeysNames.Count - 1 do
begin
try
Registry.OpenKeyReadOnly(Key + subKeysNames[h]);
Registry.GetKeyNames(subKeys);
finally
Registry.CloseKey;
end;
for i := 0 to subKeys.Count - 1 do
begin
try
if registry.OpenKeyReadOnly(Key + subKeysNames[h] + '\' + subKeys[i]) then
begin
if registry.OpenKeyReadOnly(Key + subKeysNames[h] + '\' + subKeys[i] + '\' + 'Device Parameters') then
begin
Registry.ReadBinaryData('EDID', EDID, 128);
Registry.CloseKey;
end;
MonitorName := '';
for j := 0 to 3 do
begin
if (EDID[54 + 18 * j] = 0) and
(EDID[55 + 18 * j] = 0) and
(EDID[56 + 18 * j] = 0) and
(EDID[57 + 18 * j] = $FC) and
(EDID[58 + 18 * j] = 0) then
begin
k := 0;
while (EDID[59 + 18 * j + k] <> $A) and (k < 13) do
Inc(k);
SetString(MonitorName, PAnsiChar(@EDID[59 + 18 * j]), k);
Break;
end;
end;
Result.Add(MonitorName);
end;
finally
Registry.CloseKey;
end;
end;
end;
finally
subKeys.Free;
Registry.Free;
subKeysNames.Free;
end;
end;
var
i : Integer;
begin
Writeln(GetAllMonitorName.Text);
Readln;
end.
And if you want write a program like MultiMonitorTool, you can read more information from EDID, for more information read Extended Display Identification Data