Solved

How do I identify monitor device display settings?

Posted on 2010-08-26
8
1,772 Views
Last Modified: 2013-11-05
Hi experts. How can I detect monitor display setting?
I know basic monitor information from TScreen object.
I want to find monitor index detected by windows os.

See following image:  I have 3 monitors. (1 LCD[primary], 2 USB type)
1st monior index: 1
2nd monitor index: 3
3rd monitor index: 4

How do I find that number 1,3,4 and it's additional information?


win-display-settings.jpg
0
Comment
Question by:byungho
8 Comments
 
LVL 14

Expert Comment

by:systan
ID: 33539323
try;
message WM_DEVMODECHANGE;
0
 
LVL 13

Expert Comment

by:aflarin
ID: 33539346
try this code:

procedure TForm1.Button1Click(Sender: TObject);
const
  EDD_GET_DEVICE_INTERFACE_NAME = 1;
  DISPLAY_DEVICE_ACTIVE = 1;
var
  d: TDisplayDevice;
  i: Integer;
begin
  for i:= 0 to Screen.MonitorCount do
  begin
    d.cb:= sizeof(d);
    if EnumDisplayDevices( nil, i, d, EDD_GET_DEVICE_INTERFACE_NAME) then
    begin
      Memo1.Lines.Add( 'Monitor ' + IntToStr(i) );
      Memo1.Lines.Add( d.DeviceName );
      Memo1.Lines.Add( d.DeviceString );
      if (d.StateFlags and DISPLAY_DEVICE_ACTIVE) =0 then
        Memo1.Lines.Add( 'Monitor isn''t active' );
      Memo1.Lines.Add('');
    end;
  end;
end;
0
 
LVL 13

Expert Comment

by:aflarin
ID: 33539385
What kind of additional information about display would you like to receive?

Here is the improved above code with information about display resolution and color depth:

procedure TForm1.Button1Click(Sender: TObject);
const
  EDD_GET_DEVICE_INTERFACE_NAME = 1;
  DISPLAY_DEVICE_ACTIVE = 1;
  ENUM_CURRENT_SETTINGS: DWORD = DWORD(-1);
var
  d: TDisplayDevice;
  i: Integer;
  DevMode: TDevMode;
begin
  for i:= 0 to Screen.MonitorCount do
  begin
    d.cb:= sizeof(d);
    if EnumDisplayDevices( nil, i, d, EDD_GET_DEVICE_INTERFACE_NAME) then
    begin
      Memo1.Lines.Add( 'Monitor ' + IntToStr(i) );
      if (d.StateFlags and DISPLAY_DEVICE_ACTIVE) =0 then
        Memo1.Lines.Add( 'Monitor isn''t active' );
      Memo1.Lines.Add( d.DeviceName );
      Memo1.Lines.Add( d.DeviceString );
      if EnumDisplaySettings( d.DeviceName, ENUM_CURRENT_SETTINGS, DevMode ) then
      begin
        Memo1.Lines.Add( Format( 'Resolution %d x %d', [DevMode.dmPelsWidth, DevMode.dmPelsHeight]) );
        Memo1.Lines.Add( Format( 'Bits per pixels %d', [DevMode.dmBitsPerPel]) );
      end;

      Memo1.Lines.Add('');
    end;
  end;
end;
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 33539404
here are some functions which get monitor information

i found them in this site:
http://www.koders.com/delphi/fidFCB5BAEE89BE2E945279E13B48A6801746A8946A.aspx?s=hook


Screen.Monitors[I] is TMonitor object > also has a lot of information
function UsingMultipleMonitors: Boolean;

{ Returns True if the system has more than one display monitor configured. }

var

  NumMonitors: Integer;

begin

  NumMonitors := GetSystemMetrics(80 {SM_CMONITORS});

  Result := (NumMonitors <> 0) and (NumMonitors <> 1);

  { ^ NumMonitors will be zero if not running Win98, NT 5, or later }

end;



type

  HMONITOR = type Integer;

  PMonitorInfoA = ^TMonitorInfoA;

  TMonitorInfoA = record

    cbSize: DWORD;

    rcMonitor: TRect;

    rcWork: TRect;

    dwFlags: DWORD;

  end;

const

  MONITOR_DEFAULTTONEAREST = $2;

type

  TMultiMonApis = record

    funcMonitorFromRect: function(lprcScreenCoords: PRect; dwFlags: DWORD): HMONITOR; stdcall;

    funcMonitorFromPoint: function(ptScreenCoords: TPoint; dwFlags: DWORD): HMONITOR; stdcall;

    funcMonitorFromWindow: function(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall;

    funcGetMonitorInfoA: function(hMonitor: HMONITOR; lpMonitorInfo: PMonitorInfoA): BOOL; stdcall;

  end;



{ Under D4 I could be using the MultiMon unit for the multiple monitor

  function imports, but its stubs for MonitorFromRect and MonitorFromPoint

  are seriously bugged... So I chose to avoid the MultiMon unit entirely. }



function InitMultiMonApis(var Apis: TMultiMonApis): Boolean;

var

  User32Handle: THandle;

begin

  User32Handle := GetModuleHandle(user32);

  Apis.funcMonitorFromRect := GetProcAddress(User32Handle, 'MonitorFromRect');

  Apis.funcMonitorFromPoint := GetProcAddress(User32Handle, 'MonitorFromPoint');

  Apis.funcMonitorFromWindow := GetProcAddress(User32Handle, 'MonitorFromWindow');

  Apis.funcGetMonitorInfoA := GetProcAddress(User32Handle, 'GetMonitorInfoA');

  Result := Assigned(Apis.funcMonitorFromRect) and

    Assigned(Apis.funcMonitorFromPoint) and Assigned(Apis.funcGetMonitorInfoA);

end;



function GetRectOfMonitorContainingRect(const R: TRect;

  const WorkArea: Boolean): TRect;

{ Returns the work area of the monitor which the rectangle R intersects with

  the most, or the monitor nearest R if no monitors intersect. }

var

  Apis: TMultiMonApis;

  M: HMONITOR;

  MonitorInfo: TMonitorInfoA;

begin

  if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin

    M := Apis.funcMonitorFromRect(@R, MONITOR_DEFAULTTONEAREST);

    MonitorInfo.cbSize := SizeOf(MonitorInfo);

    if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin

      if not WorkArea then

        Result := MonitorInfo.rcMonitor

      else

        Result := MonitorInfo.rcWork;

      Exit;

    end;

  end;

  Result := GetRectOfPrimaryMonitor(WorkArea);

end;



function GetRectOfMonitorContainingPoint(const P: TPoint;

  const WorkArea: Boolean): TRect;

{ Returns the screen area of the monitor containing the point P, or the monitor

  nearest P if P isn't in any monitor's work area. }

var

  Apis: TMultiMonApis;

  M: HMONITOR;

  MonitorInfo: TMonitorInfoA;

begin

  if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin

    M := Apis.funcMonitorFromPoint(P, MONITOR_DEFAULTTONEAREST);

    MonitorInfo.cbSize := SizeOf(MonitorInfo);

    if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin

      if not WorkArea then

        Result := MonitorInfo.rcMonitor

      else

        Result := MonitorInfo.rcWork;

      Exit;

    end;

  end;

  Result := GetRectOfPrimaryMonitor(WorkArea);

end;



function GetRectOfMonitorContainingWindow(const W: HWND;

  const WorkArea: Boolean): TRect;

var

  Apis: TMultiMonApis;

  M: HMONITOR;

  MonitorInfo: TMonitorInfoA;

begin

  if UsingMultipleMonitors and InitMultiMonApis(Apis) then begin

    M := Apis.funcMonitorFromWindow(W, MONITOR_DEFAULTTONEAREST);

    MonitorInfo.cbSize := SizeOf(MonitorInfo);

    if Apis.funcGetMonitorInfoA(M, @MonitorInfo) then begin

      if not WorkArea then

        Result := MonitorInfo.rcMonitor

      else

        Result := MonitorInfo.rcWork;

      Exit;

    end;

  end;

  Result := GetRectOfPrimaryMonitor(WorkArea);

end;

Open in new window

0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:byungho
ID: 33539840
to aflarin//  Additional information is BoundsRect (Left, Top, Right,Bottom)
0
 
LVL 13

Accepted Solution

by:
aflarin earned 500 total points
ID: 33540002
ok, here is it:

procedure TForm1.Button2Click(Sender: TObject);
type
  TDeviceMode2 = packed record
    dmDeviceName: array[0..CCHDEVICENAME - 1] of AnsiChar;
    dmSpecVersion: Word;
    dmDriverVersion: Word;
    dmSize: Word;
    dmDriverExtra: Word;
    dmFields: DWORD;
    dmPosition: TPoint;
    dmDisplayOrientation: DWORD;
    dmDisplayFixedOutput: DWORD;
    dmColor: SHORT;
    dmDuplex: SHORT;
    dmYResolution: SHORT;
    dmTTOption: SHORT;
    dmCollate: SHORT;
    dmFormName: array[0..CCHFORMNAME - 1] of AnsiChar;
    dmLogPixels: Word;
    dmBitsPerPel: DWORD;
    dmPelsWidth: DWORD;
    dmPelsHeight: DWORD;
    dmDisplayFlags: DWORD;
    dmDisplayFrequency: DWORD;
    dmICMMethod: DWORD;
    dmICMIntent: DWORD;
    dmMediaType: DWORD;
    dmDitherType: DWORD;
    dmICCManufacturer: DWORD;
    dmICCModel: DWORD;
    dmPanningWidth: DWORD;
    dmPanningHeight: DWORD;
  end;

const
  EDD_GET_DEVICE_INTERFACE_NAME = 1;
  DISPLAY_DEVICE_ACTIVE = 1;
  ENUM_CURRENT_SETTINGS: DWORD = DWORD(-1);
var
  d: TDisplayDevice;
  i: Integer;
  DevMode: TDevMode;
begin
  for i:= 0 to Screen.MonitorCount do
  begin
    d.cb:= sizeof(d);
    if EnumDisplayDevices( nil, i, d, EDD_GET_DEVICE_INTERFACE_NAME) then
    begin
      Memo1.Lines.Add( 'Monitor ' + IntToStr(i) );
      if (d.StateFlags and DISPLAY_DEVICE_ACTIVE) =0 then
        Memo1.Lines.Add( 'Monitor isn''t active' );
      Memo1.Lines.Add( d.DeviceName );
      Memo1.Lines.Add( d.DeviceString );
      if EnumDisplaySettings( d.DeviceName, ENUM_CURRENT_SETTINGS, DevMode ) then
      begin
        Memo1.Lines.Add( Format( 'Resolution %d x %d', [DevMode.dmPelsWidth, DevMode.dmPelsHeight]) );
        Memo1.Lines.Add( Format( 'Bits per pixels %d', [DevMode.dmBitsPerPel]) );

        Memo1.Lines.Add( Format( 'Rect %d, %d, %d, %d', [TDeviceMode2(DevMode).dmPosition.X, TDeviceMode2(DevMode).dmPosition.Y, TDeviceMode2(DevMode).dmPosition.X+DevMode.dmPelsWidth, TDeviceMode2(DevMode).dmPosition.Y+DevMode.dmPelsHeight ]) );

      end;

      Memo1.Lines.Add('');
    end;
  end;
end;
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 33540108
why make it so difficult ?

procedure TForm1.ShowInMemo(aMemo: TMemo; I: integer; aRect: TRect);
begin
  aMemo.Lines.Add(Format('Index: %d; Left: %d; Top: %d; Right: %d; Bottom: %d',
    [I, aRect.Left, a.Rect.Top, aRect.Right, aRect.Bottom]));
end;

procedure TForm1.Button1Click(Sender: TObject);
var 
  I: Integer;
  m: TMonitor;
begin
  for I := 0 to Screen.MonitorCount - 1 do
  begin
    m := Screen.Monitors[I];
    ShowInMemo(Memo1, I, m.BoundsRect);
  end;
end;

Open in new window

0
 
LVL 13

Expert Comment

by:aflarin
ID: 33540220
>> why make it so difficult ?

because the index of TMonitor (in TScreen) is not the same as the OS monitor number.

btw, don't think it's difficult :)
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now