Solved

How do I identify monitor device display settings?

Posted on 2010-08-26
8
1,889 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 

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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

763 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