Solved

How do I identify monitor device display settings?

Posted on 2010-08-26
8
1,789 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 37

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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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 37

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

863 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

24 Experts available now in Live!

Get 1:1 Help Now